diff --git a/target/linux/phytium/config-5.10 b/target/linux/phytium/config-5.10 index 8627002b8a4bfb758536a584dd496f7052a048a9..be7702f1acf776c6f5b0b799286b58cadd773e88 100644 --- a/target/linux/phytium/config-5.10 +++ b/target/linux/phytium/config-5.10 @@ -268,6 +268,7 @@ CONFIG_I2C_PHYTIUM_PLATFORM=y CONFIG_I2C_SLAVE=y # CONFIG_I2C_SLAVE_TESTUNIT is not set CONFIG_I2C_SMBUS=y +CONFIG_I2C_V2_PLATFORM=y CONFIG_I3C=y CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INDIRECT_PIO=y @@ -341,6 +342,7 @@ CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_CQHCI=y CONFIG_MMC_PHYTIUM_MCI_PCI=y CONFIG_MMC_PHYTIUM_MCI_PLTFM=y +CONFIG_MMC_PHYTIUM_MCI_PLTFM_V2=y CONFIG_MMC_PHYTIUM_SDCI=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_OF_ARASAN=y @@ -419,11 +421,14 @@ CONFIG_PHYS_ADDR_T_64BIT=y # CONFIG_PHYTIUM_GDMA is not set CONFIG_PHYTIUM_I3C_MASTER=y CONFIG_PHYTIUM_IXIC=y +CONFIG_PHYTIUM_LPC_SNOOP=y CONFIG_PHYTIUM_MBOX=y +CONFIG_PHYTIUM_SNOOP_CTRL=m CONFIG_PHYTMAC=y CONFIG_PHYTMAC_ENABLE_PTP=y CONFIG_PHYTMAC_PCI=y CONFIG_PHYTMAC_PLATFORM=y +CONFIG_PHYTNET_LED=m CONFIG_PINCTRL=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_PLATFORM_MHU=y @@ -515,6 +520,9 @@ CONFIG_SERIAL_DEV_BUS=y CONFIG_SERIAL_DEV_CTRL_TTYPORT=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_PHYTIUM_PCI is not set +CONFIG_SERIAL_PHYTIUM_UART_V2=y +# CONFIG_SERIAL_PHYTIUM_V2_DEBUG is not set CONFIG_SERIO=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIO_LIBPS2=y @@ -536,8 +544,10 @@ CONFIG_SPI_MEM=y CONFIG_SPI_PHYTIUM=y CONFIG_SPI_PHYTIUM_PCI=y CONFIG_SPI_PHYTIUM_PLAT=y +CONFIG_SPI_PHYTIUM_PLAT_V2=y CONFIG_SPI_PHYTIUM_QSPI=y CONFIG_SPI_PHYTIUM_QUADSPI=y +CONFIG_SPI_PHYTIUM_V2=y CONFIG_SPI_SPIDEV=y # CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set CONFIG_SQUASHFS_DECOMP_SINGLE=y @@ -605,6 +615,7 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_PHY=y CONFIG_USB_PHYTIUM=y +# CONFIG_USB_PHYTIUM_PCI is not set CONFIG_USB_ROLE_SWITCH=y CONFIG_USB_STORAGE=y CONFIG_USB_SUPPORT=y diff --git a/target/linux/phytium/patches-5.10/0017-Add-phytium-LPC-snoop-driver.patch b/target/linux/phytium/patches-5.10/0017-Add-phytium-LPC-snoop-driver.patch new file mode 100644 index 0000000000000000000000000000000000000000..56e852f82c60bcba0f2a4a45229f71d4a21eb5a7 --- /dev/null +++ b/target/linux/phytium/patches-5.10/0017-Add-phytium-LPC-snoop-driver.patch @@ -0,0 +1,379 @@ +From ec3a3f441d0ea72c75fa244108d74959771af420 Mon Sep 17 00:00:00 2001 +From: Huangjie +Date: Mon, 15 Jul 2024 11:04:52 +0800 +Subject: [PATCH 3/3] Add phytium LPC snoop driver + +Signed-off-by: Huangjie +--- + drivers/misc/Kconfig | 9 + + drivers/misc/Makefile | 1 + + drivers/misc/phytium-lpc-snoop.c | 325 +++++++++++++++++++++++++++++++ + 3 files changed, 335 insertions(+) + create mode 100644 drivers/misc/phytium-lpc-snoop.c + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index fafa8b0d80..0cc983acaf 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -466,6 +466,15 @@ config HISI_HIKEY_USB + switching between the dual-role USB-C port and the USB-A host ports + using only one USB controller. + ++ ++config PHYTIUM_LPC_SNOOP ++ tristate "Phytium HOST LPC snoop support" ++ depends on ARCH_PHYTIUM && REGMAP && MFD_SYSCON ++ help ++ Provides a driver to control the LPC snoop interface which ++ allows the BMC to listen on and save the data written by ++ the host to an arbitrary LPC I/O port. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index d23231e733..0d495fbc8f 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_LKDTM) += lkdtm/ + obj-$(CONFIG_TIFM_CORE) += tifm_core.o + obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o + obj-$(CONFIG_PHANTOM) += phantom.o ++obj-$(CONFIG_PHYTIUM_LPC_SNOOP) += phytium-lpc-snoop.o + obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o + obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o + obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o +diff --git a/drivers/misc/phytium-lpc-snoop.c b/drivers/misc/phytium-lpc-snoop.c +new file mode 100644 +index 0000000000..d7caa93d20 +--- /dev/null ++++ b/drivers/misc/phytium-lpc-snoop.c +@@ -0,0 +1,325 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Provides a simple driver to control the PHYTIUM LPC snoop interface which ++ * allows the BMC to listen on and save the data written by ++ * the host to an arbitrary LPC I/O port. ++ * ++ * Typically used by the BMC to "watch" host boot progress via port ++ * 0x80 writes made by the BIOS during the boot process. ++ * ++ * Copyright (c) 2019-2023, Phytium Technology Co., Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DEVICE_NAME "phytium-lpc-snoop" ++ ++#define NUM_SNOOP_CHANNELS 2 ++#define SNOOP_FIFO_SIZE 2048 ++ ++#define snp_enable_reg 0x150 ++#define snp_enable_reg_snp1_en BIT(0) ++#define snp_enable_reg_snp1_int_en BIT(1) ++#define snp_enable_reg_snp2_en BIT(2) ++#define snp_enable_reg_snp2_int_en BIT(3) ++ ++#define snp_status_reg 0x154 ++#define snp_status_reg_snp1_int BIT(0) ++#define snp_status_reg_snp2_int BIT(1) ++ ++#define snp_addr_reg 0x158 ++#define snp_addr_reg_snp1_addr GENMASK(15, 0) ++#define snp_addr_reg_snp1_shift 0 ++#define snp_addr_reg_snp2_addr GENMASK(31, 16) ++#define snp_addr_reg_snp2_shift 16 ++ ++#define snp_data_reg 0x15c ++#define snp_data_reg_snp1_data_reg GENMASK(7, 0) ++#define snp_data_reg_snp1_shift 0 ++#define snp_data_reg_snp2_data_reg GENMASK(15, 8) ++#define snp_data_reg_snp2_shift 8 ++ ++struct phytium_lpc_snoop_channel { ++ struct kfifo fifo; ++ wait_queue_head_t wq; ++ struct miscdevice miscdev; ++}; ++ ++struct phytium_lpc_snoop { ++ struct regmap *regmap; ++ int irq; ++ struct phytium_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; ++}; ++ ++static struct phytium_lpc_snoop_channel *snoop_file_to_chan(struct file *file) ++{ ++ return container_of(file->private_data, ++ struct phytium_lpc_snoop_channel, ++ miscdev); ++} ++ ++static ssize_t snoop_file_read(struct file *file, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ struct phytium_lpc_snoop_channel *chan = snoop_file_to_chan(file); ++ unsigned int copied; ++ int ret = 0; ++ ++ if (kfifo_is_empty(&chan->fifo)) { ++ if (file->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ret = wait_event_interruptible(chan->wq, ++ !kfifo_is_empty(&chan->fifo)); ++ if (ret == -ERESTARTSYS) ++ return -EINTR; ++ } ++ ret = kfifo_to_user(&chan->fifo, buffer, count, &copied); ++ ++ return ret ? ret : copied; ++} ++ ++static unsigned int snoop_file_poll(struct file *file, ++ struct poll_table_struct *pt) ++{ ++ struct phytium_lpc_snoop_channel *chan = snoop_file_to_chan(file); ++ ++ poll_wait(file, &chan->wq, pt); ++ return !kfifo_is_empty(&chan->fifo) ? POLLIN : 0; ++} ++ ++static const struct file_operations snoop_fops = { ++ .owner = THIS_MODULE, ++ .read = snoop_file_read, ++ .poll = snoop_file_poll, ++ .llseek = noop_llseek, ++}; ++ ++/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */ ++static void put_fifo_with_discard(struct phytium_lpc_snoop_channel *chan, u8 val) ++{ ++ if (!kfifo_initialized(&chan->fifo)) ++ return; ++ if (kfifo_is_full(&chan->fifo)) ++ kfifo_skip(&chan->fifo); ++ kfifo_put(&chan->fifo, val); ++ wake_up_interruptible(&chan->wq); ++} ++ ++static irqreturn_t phytium_lpc_snoop_irq(int irq, void *arg) ++{ ++ struct phytium_lpc_snoop *lpc_snoop = arg; ++ u32 reg, data; ++ ++ if (regmap_read(lpc_snoop->regmap, snp_status_reg, ®)) ++ return IRQ_NONE; ++ ++ /* Check if one of the snoop channels is interrupting */ ++ reg &= (snp_status_reg_snp1_int | snp_status_reg_snp2_int); ++ if (!reg) ++ return IRQ_NONE; ++ ++ /* Ack pending IRQs */ ++ regmap_write(lpc_snoop->regmap, snp_status_reg, reg); ++ ++ /* Read and save most recent snoop'ed data byte to FIFO */ ++ regmap_read(lpc_snoop->regmap, snp_data_reg, &data); ++ ++ if (reg & snp_status_reg_snp1_int) { ++ u8 val = (data & snp_data_reg_snp1_data_reg) >> snp_data_reg_snp1_shift; ++ ++ put_fifo_with_discard(&lpc_snoop->chan[0], val); ++ } ++ if (reg & snp_status_reg_snp2_int) { ++ u8 val = (data & snp_data_reg_snp2_data_reg) >> snp_data_reg_snp2_shift; ++ ++ put_fifo_with_discard(&lpc_snoop->chan[1], val); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int phytium_lpc_snoop_config_irq(struct phytium_lpc_snoop *lpc_snoop, ++ struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ int rc; ++ ++ lpc_snoop->irq = platform_get_irq(pdev, 0); ++ if (!lpc_snoop->irq) ++ return -ENODEV; ++ ++ rc = devm_request_irq(dev, lpc_snoop->irq, ++ phytium_lpc_snoop_irq, IRQF_SHARED, ++ DEVICE_NAME, lpc_snoop); ++ if (rc < 0) { ++ dev_warn(dev, "Unable to request IRQ %d\n", lpc_snoop->irq); ++ lpc_snoop->irq = 0; ++ return rc; ++ } ++ ++ return 0; ++} ++ ++static int phytium_lpc_enable_snoop(struct phytium_lpc_snoop *lpc_snoop, ++ struct device *dev, ++ int channel, u16 lpc_port) ++{ ++ int rc = 0; ++ u32 snp_enable_reg_en, snp_addr_reg_mask, snp_addr_reg_shift; ++ ++ init_waitqueue_head(&lpc_snoop->chan[channel].wq); ++ /* Create FIFO datastructure */ ++ rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo, ++ SNOOP_FIFO_SIZE, GFP_KERNEL); ++ if (rc) ++ return rc; ++ ++ lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; ++ lpc_snoop->chan[channel].miscdev.name = ++ devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel); ++ lpc_snoop->chan[channel].miscdev.fops = &snoop_fops; ++ lpc_snoop->chan[channel].miscdev.parent = dev; ++ rc = misc_register(&lpc_snoop->chan[channel].miscdev); ++ if (rc) ++ return rc; ++ ++ /* Enable LPC snoop channel at requested port */ ++ switch (channel) { ++ case 0: ++ snp_enable_reg_en = snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en; ++ snp_addr_reg_mask = snp_addr_reg_snp1_addr; ++ snp_addr_reg_shift = snp_addr_reg_snp1_shift; ++ break; ++ case 1: ++ snp_enable_reg_en = snp_enable_reg_snp2_en | snp_enable_reg_snp2_int_en; ++ snp_addr_reg_mask = snp_addr_reg_snp2_addr; ++ snp_addr_reg_shift = snp_addr_reg_snp2_shift; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, snp_enable_reg_en, snp_enable_reg_en); ++ regmap_update_bits(lpc_snoop->regmap, snp_addr_reg, snp_addr_reg_mask, ++ lpc_port << snp_addr_reg_shift); ++ return rc; ++} ++ ++static void phytium_lpc_disable_snoop(struct phytium_lpc_snoop *lpc_snoop, ++ int channel) ++{ ++ switch (channel) { ++ case 0: ++ regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, ++ snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en, ++ 0); ++ break; ++ case 1: ++ regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, ++ snp_enable_reg_snp2_en | snp_enable_reg_snp2_int_en, ++ 0); ++ break; ++ default: ++ return; ++ } ++ ++ kfifo_free(&lpc_snoop->chan[channel].fifo); ++ misc_deregister(&lpc_snoop->chan[channel].miscdev); ++} ++ ++static int phytium_lpc_snoop_probe(struct platform_device *pdev) ++{ ++ struct phytium_lpc_snoop *lpc_snoop; ++ struct device *dev; ++ u32 port; ++ int rc; ++ ++ dev = &pdev->dev; ++ ++ lpc_snoop = devm_kzalloc(dev, sizeof(*lpc_snoop), GFP_KERNEL); ++ if (!lpc_snoop) ++ return -ENOMEM; ++ ++ lpc_snoop->regmap = syscon_node_to_regmap( ++ pdev->dev.parent->of_node); ++ if (IS_ERR(lpc_snoop->regmap)) { ++ dev_err(dev, "Couldn't get regmap\n"); ++ return -ENODEV; ++ } ++ ++ dev_set_drvdata(&pdev->dev, lpc_snoop); ++ ++ rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port); ++ if (rc) { ++ dev_err(dev, "no snoop ports configured\n"); ++ return -ENODEV; ++ } ++ ++ rc = phytium_lpc_snoop_config_irq(lpc_snoop, pdev); ++ if (rc) ++ return rc; ++ ++ rc = phytium_lpc_enable_snoop(lpc_snoop, dev, 0, port); ++ if (rc) ++ return rc; ++ ++ /* Configuration of 2nd snoop channel port is optional */ ++ if (of_property_read_u32_index(dev->of_node, "snoop-ports", ++ 1, &port) == 0) { ++ rc = phytium_lpc_enable_snoop(lpc_snoop, dev, 1, port); ++ if (rc) ++ phytium_lpc_disable_snoop(lpc_snoop, 0); ++ } ++ ++ return rc; ++} ++ ++static int phytium_lpc_snoop_remove(struct platform_device *pdev) ++{ ++ struct phytium_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); ++ ++ /* Disable both snoop channels */ ++ phytium_lpc_disable_snoop(lpc_snoop, 0); ++ phytium_lpc_disable_snoop(lpc_snoop, 1); ++ ++ return 0; ++} ++ ++ ++static const struct of_device_id phytium_lpc_snoop_match[] = { ++ { .compatible = "phytium,lpc-snoop"}, ++ { }, ++}; ++ ++static struct platform_driver phytium_lpc_snoop_driver = { ++ .driver = { ++ .name = DEVICE_NAME, ++ .of_match_table = phytium_lpc_snoop_match, ++ }, ++ .probe = phytium_lpc_snoop_probe, ++ .remove = phytium_lpc_snoop_remove, ++}; ++ ++module_platform_driver(phytium_lpc_snoop_driver); ++ ++MODULE_DEVICE_TABLE(of, phytium_lpc_snoop_match); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lan Hengyu lanhengyu1395@phytium.com.cn"); ++MODULE_DESCRIPTION("Driver to control Phytium LPC snoop functionality"); +-- +2.34.1 + diff --git a/target/linux/phytium/patches-5.10/0020-sync_kernel-5.10_v2.3.patch b/target/linux/phytium/patches-5.10/0020-sync_kernel-5.10_v2.3.patch new file mode 100644 index 0000000000000000000000000000000000000000..eef158ab6b3186545da103132765df816e2e98bd --- /dev/null +++ b/target/linux/phytium/patches-5.10/0020-sync_kernel-5.10_v2.3.patch @@ -0,0 +1,78436 @@ +diff --git a/Documentation/devicetree/bindings/i2c/phytium,i2c-2.0.yaml b/Documentation/devicetree/bindings/i2c/phytium,i2c-2.0.yaml +new file mode 100644 +index 000000000000..e02036e33768 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/phytium,i2c-2.0.yaml +@@ -0,0 +1,92 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++ ++title: Phytium I2C Controller ++ ++maintainers: ++ - WuJinyong ++ ++properties: ++ compatible: ++ - description: Phytium I2C controller ++ const: phytium,i2c-2.0 ++ ++ reg: ++ minItems: 1 ++ items: ++ - description: Offset and length of the memory mapped registers ++ - description: Offset and length of the memory mapped share memory address ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 1 ++ items: ++ - description: I2C controller reference clock source ++ ++ clock-frequency: ++ description: Desired I2C bus clock frequency in Hz ++ enum: [100000, 400000, 1000000, 3400000] ++ default: 400000 ++ ++ i2c-sda-hold-time-ns: ++ description: | ++ The property should contain the SDA hold time in nanoseconds. This option ++ is only supported in hardware blocks version 1.11a or newer or on ++ Microsemi SoCs. ++ ++ i2c-scl-falling-time-ns: ++ description: | ++ The property should contain the SCL falling time in nanoseconds. ++ This value is used to compute the tLOW period. ++ default: 300 ++ ++ i2c-sda-falling-time-ns: ++ description: | ++ The property should contain the SDA falling time in nanoseconds. ++ This value is used to compute the tHIGH period. ++ default: 300 ++ ++unevaluatedProperties: false ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ ++examples: ++ - | ++ i2c@0x2701a000 { ++ compatible = "phytium,i2c-2.0"; ++ reg = <0x0 0x2701a000 0x0 0x1000 0x0 0x2701e000 0x0 0x200>; ++ interrupts = ; ++ clock-frequency = <400000>; ++ }; ++ - | ++ i2c@2701a000 { ++ compatible = "phytium,i2c-2.0"; ++ reg = <0x0 0x2701a000 0x0 0x1000 0x0 0x2701e000 0x0 0x200>; ++ interrupts = ; ++ clock-frequency = <400000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <300>; ++ i2c-scl-falling-time-ns = <300>; ++ }; ++ - | ++ i2c@2701a000 { ++ compatible = "phytium,i2c-2.0"; ++ reg = <0x0 0x2701a000 0x0 0x1000 0x0 0x2701e000 0x0 0x200>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ clocks = <&i2cclk>; ++ interrupts = ; ++ ++ eeprom@64 { ++ compatible = "atmel,24c02"; ++ reg = <0x64>; ++ }; ++ }; ++... +diff --git a/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml +new file mode 100644 +index 000000000000..0e004735fd38 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml +@@ -0,0 +1,35 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++ ++* Phytium I3C controller ++ ++This I3C controller is for Phytium Soc. ++ ++Required properties: ++- compatible: Shall be "phytium,cdns-i3c-master" ++- clocks: Shall reference the pclk and sysclk ++- clock-names: Shall contain "pclk" and "sysclk" ++- interrupts: The interrupt line connected to this I3C master ++- reg: I3C master registers ++- #address-cells: Shall be set to 1 ++- #size-cells: Shall be set to 0 ++- i2c-scl-hz: I2C CLK frequency ++- i3c-scl-hz: I3C CLK frequency ++ ++Example: ++ ++ i3c-master@28045000 { ++ compatible = "phytium,cdns-i3c-master"; ++ reg = <0x0 0x28045000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&coreclock>, <&i3csysclock>; ++ clock-names = "pclk", "sysclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c-scl-hz = <400000>; ++ i3c-scl-hz = <1000000>; ++ ++ nunchuk: nunchuk@52 { ++ compatible = "nintendo,nunchuk"; ++ reg = <0x52 0x0 0x10>; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/leds/phytnet_led.yaml b/Documentation/devicetree/bindings/leds/phytnet_led.yaml +new file mode 100644 +index 000000000000..ae0acf9ec5ec +--- /dev/null ++++ b/Documentation/devicetree/bindings/leds/phytnet_led.yaml +@@ -0,0 +1,46 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/phytnet_led.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Phytium mac led controller ++ ++maintainers: ++ - LongShixiang ++ ++description: ++ This modules is used to control mac led. ++ ++properties: ++ compatible: ++ const: phytium,net_led ++ net_dev: ++ maxItems: 1 ++ description: Phandler of specified Net device ++ led-gpios: ++ minItems: 1 ++ maxItems: 2 ++ description: |- ++ the gpios used for led control based on net_dev condition. ++ One represents LINK condition, another represents ACT condition. ++ ++required: ++ - compatible ++ - net_dev ++ - led-gpios ++ ++examples: ++ - | ++ gpiochip0: gpop_controller{ ++ ... ++ } ++ eth0: ethernet{ ++ ... ++ } ++ phytium_net_led0 { ++ compatible = "phytium,net_led"; ++ net_dev = <ð0>; ++ led-gpios = <&gpiochip0 9 GPIO_ACTIVE_HIGH>, /* link */ ++ <&gpiochip0 11 GPIO_ACTIVE_HIGH>; /* act */ ++ }; +diff --git a/Documentation/devicetree/bindings/mmc/phytium,mci_v2.yaml b/Documentation/devicetree/bindings/mmc/phytium,mci_v2.yaml +new file mode 100644 +index 000000000000..26ae78ffa162 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mmc/phytium,mci_v2.yaml +@@ -0,0 +1,69 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mmc/phytium,mci_v2.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Phytium Multimedia Card Interface controller ++ ++description: | ++ The highspeed MMC host V2 controller on Phytium SoCs provides an interface ++ for MMC, SD and SDIO types of memory cards. ++ ++maintainers: ++ - Lai Xueyu ++ ++allOf: ++ - $ref: "mmc-controller.yaml" ++ ++properties: ++ compatible: ++ const: phytium,mci_2.0 ++ ++ reg: ++ maxItems: 2 ++ description: mmc controller regfile base registers. ++ description: mmc controller share memory base registers. ++ ++ interrupts: ++ maxItems: 1 ++ description: mmc controller v2 interrupt. ++ ++ clocks: ++ maxItems: 1 ++ description: phandles to input clocks. ++ ++ clock-names: ++ items: ++ - const: phytium_mci_clk ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ ++examples: ++ - | ++ mmc0_v2: mmc@27018000 { ++ compatible = "phytium,mci_2.0"; ++ reg = <0x0 0x27018000 0x0 0x1000>, ++ <0x0 0x26fea000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&sysclk_1200mhz>; ++ clock-names = "phytium_mci_clk"; ++ status = "disabled"; ++ }; ++ ++ &mmc0 { ++ bus-width = <4>; ++ max-frequency = <50000000>; ++ cap-sdio-irq; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ no-mmc; ++ status = "ok"; ++ }; +diff --git a/Documentation/devicetree/bindings/reset/phytium_reset.yaml b/Documentation/devicetree/bindings/reset/phytium_reset.yaml +new file mode 100644 +index 000000000000..82171da5f5e9 +--- /dev/null ++++ b/Documentation/devicetree/bindings/reset/phytium_reset.yaml +@@ -0,0 +1,49 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++title: Phytium Reset Controller ++====================================== ++ ++This binding describes a reset-controller for Phytium SoCs. ++ ++Required properties: ++- compatible: ++ Usage: required ++ Value type: ++ Definition: must be: ++ "phytium,reset" ++ ++- reg: ++ Usage: required ++ Value type: ++ Definition: must specify the base address and size of the register ++ space. ++ ++- #reset-cells: ++ Usage: required ++ Value type: ++ Definition: must be 1; cell entry represents the reset index. ++ ++Example: ++ ++reset: reset@2807e000 { ++ compatible = "phytium,reset"; ++ reg = <0x0 0x2807e000 0x0 0x10>; ++ #reset-cells = <1>; ++}; ++ ++Specifying reset lines connected to IP modules ++============================================== ++ ++Device nodes that need access to reset lines should ++specify them as a reset phandle in their corresponding node. ++ ++Example: ++ ++i2c0: i2c@28011000 { ++ ... ++ ++ resets = <&reset 0>; ++ ++ ... ++}; +diff --git a/Documentation/devicetree/bindings/serial/phytium,uart-2.0.yaml b/Documentation/devicetree/bindings/serial/phytium,uart-2.0.yaml +new file mode 100644 +index 000000000000..df2c8bca6a67 +--- /dev/null ++++ b/Documentation/devicetree/bindings/serial/phytium,uart-2.0.yaml +@@ -0,0 +1,69 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/serial/phytium,uart-v2.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Phytium serial UART v2 ++ ++maintainers: ++ - Hengyu Lan ++ ++allOf: ++ - $ref: serial.yaml# ++ ++# Need a custom select here or 'arm,primecell' will match on lots of nodes ++select: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - phytium,uart-2.0 ++ required: ++ - compatible ++ ++properties: ++ compatible: ++ items: ++ - const: phytium,uart-2.0 ++ ++ reg: ++ maxItems: 2 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ description: ++ When present, the first clock listed must correspond to ++ the clock named UARTCLK on the IP block, i.e. the clock ++ to the external serial line, whereas the second clock ++ must correspond to the PCLK clocking the internal logic ++ of the block. Just listing one clock (the first one) is ++ deprecated. ++ maxItems: 2 ++ ++ clock-names: ++ items: ++ - const: uartclk ++ - const: apb_pclk ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ uart@27011000 { ++ compatible = "phytium,uart-2.0"; ++ reg = <0x0 0x27011000 0x0 0x1000>, ++ <0x0 0x26fe4000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&sysclk_100mhz &sysclk_100mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ status = "disabled"; ++ }; ++... +diff --git a/Documentation/devicetree/bindings/spi/spi-phytium-v2.yaml b/Documentation/devicetree/bindings/spi/spi-phytium-v2.yaml +new file mode 100644 +index 000000000000..15f332ef0536 +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-phytium-v2.yaml +@@ -0,0 +1,46 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++title: Phytium SPI-V2 controller ++ ++maintainers: ++ - Peng Min ++ ++allOf: ++ - $ref: spi-v2-controller.yaml# ++ ++properties: ++ compatible: ++ const: phytium,spi-2.0 ++ ++ reg: ++ minItems: 1 ++ description: address and length of the sharememory and regfile ++ ++ interrupts: ++ maxItems: 1 ++ description: should contain one interrupt ++ ++ clocks: ++ maxItems: 1 ++ description: spi clock phandle ++ ++required: ++ - compatible ++ - "#address-cells" ++ - "#size-cells" ++ - reg ++ - interrupts ++ - clocks ++ - num-cs ++ ++examples: ++ - | ++ ++ spi0: spi@2800c000 { ++ compatible = "phytium,spi-2.0"; ++ interrupts = ; ++ reg = <0x0 0x27014000 0x0 0x1000 0x0 0x27007000 0x0 0x1000>; ++ clocks = <&sysclk_48mhz>; ++ num-cs = <4>; ++ }; +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index b4e65d1ede26..ea0d81b2b073 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -508,4 +508,6 @@ config RANDOM_TRUST_BOOTLOADER + believe its RNG facilities may be faulty. This may also be configured + at boot time with "random.trust_bootloader=on/off". + ++source "drivers/char/phytnetled/Kconfig" ++ + endmenu +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index ffce287ef415..3ccc78c1d8df 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o + obj-$(CONFIG_XILLYBUS) += xillybus/ + obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o + obj-$(CONFIG_ADI) += adi.o ++obj-$(CONFIG_PHYTNET_LED) += phytnetled/ +diff --git a/drivers/char/phytnetled/Kconfig b/drivers/char/phytnetled/Kconfig +new file mode 100644 +index 000000000000..c868ef6f53b4 +--- /dev/null ++++ b/drivers/char/phytnetled/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# PCMCIA character device configuration ++# ++config PHYTNET_LED ++ tristate "Phytium mac led control module" ++ depends on PHYTMAC ++ depends on GPIO_PHYTIUM_PLAT ++ default m ++ help ++ If you have a network (Ethernet) controller of this type and ++ want to use it control port led say Y or M here. +\ No newline at end of file +diff --git a/drivers/char/phytnetled/Makefile b/drivers/char/phytnetled/Makefile +new file mode 100644 +index 000000000000..ea129f5e485b +--- /dev/null ++++ b/drivers/char/phytnetled/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_PHYTNET_LED) += phytnet_led.o +diff --git a/drivers/char/phytnetled/phytnet_led.c b/drivers/char/phytnetled/phytnet_led.c +new file mode 100644 +index 000000000000..b1033f7ab89f +--- /dev/null ++++ b/drivers/char/phytnetled/phytnet_led.c +@@ -0,0 +1,323 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022-2023 Phytium Technology Co.,Ltd. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "phytnet_led.h" ++ ++#define DRIVER_NAME "phytnet_led" ++#define DRIVER_VERSION "1.0" ++#define DRIVER_AUTHOR "LongShixiang " ++#define DRIVER_DESC "net device led control module" ++#define NET_DEV_PROPNAME "net_dev" ++#define LED_OF_NAME "led" ++#define CHECK_INTERVAL 125 /* Unit: ms */ ++#define NDEV_CHECK_DELAY 30000 /* Unit: 30s */ ++#define LED_ON 1 ++#define LED_OFF 0 ++#define LINK_OFFSET 0 ++#define ACT_OFFSET 1 ++ ++#if defined(CONFIG_OF) ++static const struct of_device_id phytnet_led_of_ids[] = { ++ { .compatible = "phytium,net_led"}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, phytnet_led_of_ids); ++#endif /* CONFIG_OF */ ++ ++#ifdef CONFIG_ACPI ++static const struct acpi_device_id phytnet_acpi_ids[] = { ++ { .id = "PHYT800C"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, phytnet_acpi_ids); ++#else ++#define phytnet_acpi_ids NULL ++#endif /* CONFIG_ACPI */ ++ ++static void ++led_on(struct gpio_desc *gd) ++{ ++ gpiod_set_value(gd, LED_ON); ++} ++ ++static void ++led_off(struct gpio_desc *gd) ++{ ++ gpiod_set_value(gd, LED_OFF); ++} ++ ++static void ++led_blink(struct led_data *phytnet_led) ++{ ++ phytnet_led->act_val = !phytnet_led->act_val; ++ gpiod_set_value(phytnet_led->act, phytnet_led->act_val); ++} ++ ++static int ++port_is_linkup(struct led_data *phytnet_led) ++{ ++ if (netif_carrier_ok(phytnet_led->ndev)) ++ return true; ++ else ++ return false; ++} ++ ++static bool ++port_is_act(struct led_data *phytnet_led) ++{ ++ bool ret = false; ++ ++ if (phytnet_led->ndev_rx != phytnet_led->ndev->stats.rx_packets) { ++ phytnet_led->ndev_rx = phytnet_led->ndev->stats.rx_packets; ++ ret = true; ++ } ++ ++ if (phytnet_led->ndev_tx != phytnet_led->ndev->stats.tx_packets) { ++ phytnet_led->ndev_tx = phytnet_led->ndev->stats.tx_packets; ++ ret = true; ++ } ++ ++ return ret; ++} ++ ++static void ++led_control(struct led_data *phytnet_led) ++{ ++ while (!phytnet_led->led_stop) { ++ msleep(CHECK_INTERVAL); ++ ++ if (!netif_running(phytnet_led->ndev)) { ++ led_off(phytnet_led->link); ++ led_off(phytnet_led->act); ++ continue; ++ } ++ ++ if (port_is_linkup(phytnet_led)) ++ led_on(phytnet_led->link); ++ else ++ led_off(phytnet_led->link); ++ ++ if (port_is_act(phytnet_led)) ++ led_blink(phytnet_led); ++ else ++ led_off(phytnet_led->act); ++ } ++} ++ ++static int ++of_ndev_init(struct led_data *phytnet_led) ++{ ++ struct device_node *net_node; ++ ++ net_node = of_parse_phandle(phytnet_led->pdev->dev.of_node, NET_DEV_PROPNAME, 0); ++ if (!net_node) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get netdev ofnode from device tree\n"); ++ return -ENODEV; ++ } ++ ++ phytnet_led->ndev = of_find_net_device_by_node(net_node); ++ ++ if (!phytnet_led->ndev) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get acpi ndev\n"); ++ return -ENODEV; ++ } ++ ++ dev_info(&phytnet_led->pdev->dev, "Successfully get ndev...\n"); ++ dev_hold(phytnet_led->ndev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_ACPI ++ ++static int ++acpi_ndev_init(struct led_data *phytnet_led) ++{ ++ int err; ++ struct net_device *find_ndev; ++ const char *ndev_acpi_path; ++ acpi_handle net_handler; ++ struct acpi_device *adev; ++ acpi_status status; ++ struct device *find_dev; ++ ++ err = device_property_read_string(&phytnet_led->pdev->dev, ++ NET_DEV_PROPNAME, &ndev_acpi_path); ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to read net_dev property!\n"); ++ return -ENODEV; ++ } ++ ++ status = acpi_get_handle(NULL, (acpi_string)ndev_acpi_path, &net_handler); ++ if (ACPI_FAILURE(status)) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get acpi handler on path: %s\n", ++ ndev_acpi_path); ++ return -ENODEV; ++ } ++ ++ err = acpi_bus_get_device(net_handler, &adev); ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get adev dev\n"); ++ return -ENODEV; ++ } ++ ++ for_each_netdev(&init_net, find_ndev) { ++ if (find_ndev->dev.parent != NULL) { ++ find_dev = find_ndev->dev.parent; ++ if (&adev->fwnode == find_dev->fwnode) ++ phytnet_led->ndev = find_ndev; ++ } ++ } ++ ++ if (!phytnet_led->ndev) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get acpi ndev\n"); ++ return -ENODEV; ++ } ++ ++ dev_info(&phytnet_led->pdev->dev, "Successfully get ndev...\n"); ++ dev_hold(phytnet_led->ndev); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_ACPI */ ++ ++static int ++gpio_init(struct led_data *phytnet_led) ++{ ++ int err; ++ ++ phytnet_led->link = gpiod_get_index(&phytnet_led->pdev->dev, LED_OF_NAME, ++ LINK_OFFSET, GPIOD_OUT_HIGH); ++ if (IS_ERR(phytnet_led->link)) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get link led gpio, err code: %ld\n", ++ PTR_ERR(phytnet_led->link)); ++ ++ return PTR_ERR(phytnet_led->link); ++ } ++ ++ err = gpiod_direction_output(phytnet_led->link, LED_OFF); ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to set linkled dir, err code: %ld\n", ++ PTR_ERR(phytnet_led->link)); ++ return err; ++ } ++ ++ phytnet_led->act = gpiod_get_index(&phytnet_led->pdev->dev, LED_OF_NAME, ++ ACT_OFFSET, GPIOD_OUT_HIGH); ++ if (IS_ERR(phytnet_led->act)) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to get actled gpio, err code:%d\n", err); ++ return PTR_ERR(phytnet_led->act); ++ } ++ ++ err = gpiod_direction_output(phytnet_led->act, LED_OFF); ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "Failed to set act led gpio dir, err:%d\n", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void ++led_init_and_control(struct work_struct *work) ++{ ++ int err = -1; ++ struct led_data *phytnet_led = container_of(work, struct led_data, led_control_work.work); ++ ++ if (phytnet_led->pdev->dev.of_node) ++ err = of_ndev_init(phytnet_led); ++ else if (has_acpi_companion(&phytnet_led->pdev->dev)) ++#ifdef CONFIG_ACPI ++ err = acpi_ndev_init(phytnet_led); ++#endif /* CONFIG_ACPI */ ++ ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "ndev init wrong\n"); ++ return; ++ } ++ ++ err = gpio_init(phytnet_led); ++ if (err) { ++ dev_err(&phytnet_led->pdev->dev, "gpio init wrong\n"); ++ return; ++ } ++ ++ led_control(phytnet_led); ++} ++ ++static int ++net_led_probe(struct platform_device *pdev) ++{ ++ struct led_data *phytnet_led; ++ ++ phytnet_led = devm_kzalloc(&pdev->dev, sizeof(struct led_data), GFP_KERNEL); ++ if (!phytnet_led) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phytnet_led); ++ ++ phytnet_led->act = LED_OFF; ++ phytnet_led->pdev = pdev; ++ phytnet_led->led_stop = 0; ++ ++ INIT_DELAYED_WORK(&phytnet_led->led_control_work, led_init_and_control); ++ schedule_delayed_work(&phytnet_led->led_control_work, msecs_to_jiffies(NDEV_CHECK_DELAY)); ++ ++ return 0; ++} ++ ++static int ++net_led_remove(struct platform_device *pdev) ++{ ++ struct led_data *phytnet_led = platform_get_drvdata(pdev); ++ ++ phytnet_led->led_stop = 1; ++ cancel_delayed_work_sync(&phytnet_led->led_control_work); ++ ++ if (phytnet_led->ndev) ++ dev_put(phytnet_led->ndev); ++ ++ if (phytnet_led->link) { ++ led_off(phytnet_led->link); ++ gpiod_put(phytnet_led->link); ++ } ++ ++ if (phytnet_led->act) { ++ led_off(phytnet_led->act); ++ gpiod_put(phytnet_led->act); ++ } ++ ++ if (&pdev->dev) ++ devm_kfree(&pdev->dev, phytnet_led); ++ ++ return 0; ++} ++ ++static struct platform_driver net_led_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRIVER_NAME, ++ .of_match_table = of_match_ptr(phytnet_led_of_ids), ++ .acpi_match_table = ACPI_PTR(phytnet_acpi_ids), ++ }, ++ .probe = net_led_probe, ++ .remove = net_led_remove, ++}; ++ ++module_platform_driver(net_led_driver); ++ ++MODULE_VERSION(DRIVER_VERSION); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/char/phytnetled/phytnet_led.h b/drivers/char/phytnetled/phytnet_led.h +new file mode 100644 +index 000000000000..8f2fbadde0f8 +--- /dev/null ++++ b/drivers/char/phytnetled/phytnet_led.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2022-2023 Phytium Technology Co.,Ltd. ++ * ++ */ ++struct led_data { ++ struct platform_device *pdev; ++ struct net_device *ndev; ++ unsigned long ndev_rx, ndev_tx; ++ struct gpio_desc *link, *act; ++ struct delayed_work led_control_work; ++ int led_stop; ++ int act_val; ++}; +diff --git a/drivers/dma/phytium/phytium-gdmac.c b/drivers/dma/phytium/phytium-gdmac.c +index 3fdf572196b0..0154d6151e52 100644 +--- a/drivers/dma/phytium/phytium-gdmac.c ++++ b/drivers/dma/phytium/phytium-gdmac.c +@@ -29,7 +29,7 @@ + #include + #include "phytium-gdmac.h" + +-#define PHYTIUM_GDMA_DRIVER_VERSION "1.0.2" ++#define PHYTIUM_GDMA_DRIVER_VERSION "1.0.3" + + static inline struct phytium_gdma_device *to_gdma_device(struct dma_chan *chan) + { +@@ -475,8 +475,6 @@ static int phytium_gdma_terminate_all(struct dma_chan *chan) + { + struct phytium_gdma_chan *gdma_chan = to_gdma_chan(chan); + unsigned long flags = 0; +- u32 val = 0; +- int ret = 0; + LIST_HEAD(head); + + spin_lock_irqsave(&gdma_chan->vchan.lock, flags); +@@ -487,12 +485,9 @@ static int phytium_gdma_terminate_all(struct dma_chan *chan) + vchan_terminate_vdesc(&gdma_chan->desc->vdesc); + gdma_chan->desc = NULL; + phytium_chan_disable(gdma_chan); +- ret = readl_poll_timeout(gdma_chan->base + DMA_CX_STATE, val, +- ~(val & BIT(4)), 10, 10000); +- if (ret) +- dev_err(chan_to_dev(gdma_chan), +- "failed to complete writes\n"); + phytium_chan_reset(gdma_chan); ++ phytium_chan_irq_disable(gdma_chan); ++ phytium_chan_clk_disable(gdma_chan); + } + + vchan_get_all_descriptors(&gdma_chan->vchan, &head); +@@ -524,10 +519,11 @@ static void phytium_gdma_free_chan_resources(struct dma_chan *chan) + + phytium_chan_disable(gdma_chan); + phytium_chan_irq_disable(gdma_chan); ++ phytium_chan_clk_disable(gdma_chan); + + vchan_free_chan_resources(&gdma_chan->vchan); + +- dev_dbg(gdma->dev, "free channel %d\n", gdma_chan->id); ++ dev_info(gdma->dev, "free channel %d\n", gdma_chan->id); + } + + static int phytium_gdma_slave_config(struct dma_chan *chan, +@@ -753,8 +749,6 @@ static irqreturn_t phytium_dma_interrupt(int irq, void *dev_id) + + if (gdma->chan[i].desc) { + phytium_chan_irq_handler(gdma_chan); +- phytium_chan_disable(gdma_chan); +- phytium_chan_clk_disable(gdma_chan); + } + } + } +diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c +index e1681bba3337..6a25d71b3c72 100644 +--- a/drivers/firmware/arm_scmi/driver.c ++++ b/drivers/firmware/arm_scmi/driver.c +@@ -51,8 +51,6 @@ static LIST_HEAD(scmi_list); + static DEFINE_MUTEX(scmi_list_mutex); + /* Track the unique id for the transfers for debug & profiling purpose */ + static atomic_t transfer_last_id; +-/* Protection for scmi xfer, prevent transmission timeout */ +-static DEFINE_MUTEX(scmi_xfer_mutex); + + /** + * struct scmi_xfers_info - Structure to manage transfer information +@@ -370,9 +368,6 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) + xfer->hdr.poll_completion = true; + #endif + +- /* lock scmi xfer, too many scmi xfers may cause timeout */ +- mutex_lock(&scmi_xfer_mutex); +- + trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, + xfer->hdr.protocol_id, xfer->hdr.seq, + xfer->hdr.poll_completion); +@@ -380,7 +375,6 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) + ret = info->desc->ops->send_message(cinfo, xfer); + if (ret < 0) { + dev_dbg(dev, "Failed to send message %d\n", ret); +- mutex_unlock(&scmi_xfer_mutex); + return ret; + } + +@@ -413,7 +407,6 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) + + trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, + xfer->hdr.protocol_id, xfer->hdr.seq, ret); +- mutex_unlock(&scmi_xfer_mutex); + + return ret; + } +diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c +index 4626404be541..6282015fd74b 100644 +--- a/drivers/firmware/arm_scmi/mailbox.c ++++ b/drivers/firmware/arm_scmi/mailbox.c +@@ -22,12 +22,14 @@ + * @chan: Transmit/Receive mailbox channel + * @cinfo: SCMI channel info + * @shmem: Transmit/Receive shared memory area ++ * @chan_lock: Lock that prevents multiple xfers from being queued + */ + struct scmi_mailbox { + struct mbox_client cl; + struct mbox_chan *chan; + struct scmi_chan_info *cinfo; + struct scmi_shared_mem __iomem *shmem; ++ struct mutex chan_lock; + }; + + #define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl) +@@ -101,6 +103,7 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, + + cinfo->transport_info = smbox; + smbox->cinfo = cinfo; ++ mutex_init(&smbox->chan_lock); + + return 0; + } +@@ -128,26 +131,33 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo, + struct scmi_mailbox *smbox = cinfo->transport_info; + int ret; + +- ret = mbox_send_message(smbox->chan, xfer); ++ /* ++ * The mailbox layer has its own queue. However the mailbox queue ++ * confuses the per message SCMI timeouts since the clock starts when ++ * the message is submitted into the mailbox queue. So when multiple ++ * messages are queued up the clock starts on all messages instead of ++ * only the one inflight. ++ */ ++ mutex_lock(&smbox->chan_lock); + +- /* mbox_send_message returns non-negative value on success, so reset */ +- if (ret > 0) +- ret = 0; ++ ret = mbox_send_message(smbox->chan, xfer); ++ /* mbox_send_message returns non-negative value on success */ ++ if (ret < 0) { ++ mutex_unlock(&smbox->chan_lock); ++ return ret; ++ } + +- return ret; ++ return 0; + } + + static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret) + { + struct scmi_mailbox *smbox = cinfo->transport_info; + +- /* +- * NOTE: we might prefer not to need the mailbox ticker to manage the +- * transfer queueing since the protocol layer queues things by itself. +- * Unfortunately, we have to kick the mailbox framework after we have +- * received our message. +- */ + mbox_client_txdone(smbox->chan, ret); ++ ++ /* Release channel */ ++ mutex_unlock(&smbox->chan_lock); + } + + static void mailbox_fetch_response(struct scmi_chan_info *cinfo, +diff --git a/drivers/gpio/gpio-phytium-core.c b/drivers/gpio/gpio-phytium-core.c +index a1794f55a5a0..dce2fe463991 100644 +--- a/drivers/gpio/gpio-phytium-core.c ++++ b/drivers/gpio/gpio-phytium-core.c +@@ -128,14 +128,13 @@ int phytium_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, + return -EINVAL; + ddr = gpio->regs + GPIO_SWPORTA_DDR + (loc.port * GPIO_PORT_STRIDE); + ++ phytium_gpio_set(gc, offset, value); + raw_spin_lock_irqsave(&gpio->lock, flags); + + writel(readl(ddr) | BIT(loc.offset), ddr); + + raw_spin_unlock_irqrestore(&gpio->lock, flags); + +- phytium_gpio_set(gc, offset, value); +- + return 0; + } + EXPORT_SYMBOL_GPL(phytium_gpio_direction_output); +@@ -267,6 +266,8 @@ void phytium_gpio_irq_enable(struct irq_data *d) + unsigned long flags; + u32 val; + ++ if (gpio->is_resuming) ++ return; + /* Only port A can provide interrupt source */ + if (irqd_to_hwirq(d) >= gpio->ngpio[0]) + return; +@@ -309,19 +310,36 @@ void phytium_gpio_irq_handler(struct irq_desc *desc) + struct irq_chip *irqchip = irq_desc_get_chip(desc); + unsigned long pending; + int offset; ++ int index = -1; ++ unsigned int index_flag = 0; + + chained_irq_enter(irqchip, desc); + + pending = readl(gpio->regs + GPIO_INTSTATUS); ++ ++ if (gc->irq.num_parents > 1) { ++ for (index = 0 ; index < gc->irq.num_parents; index++) { ++ if (gc->irq.parents[index] == desc->irq_data.irq) { ++ index_flag = 1; ++ break; ++ } ++ } ++ if (index_flag == 0) { ++ pr_err("Can't find index for this gpio interrupt.\n"); ++ index = -1; ++ } ++ } ++ + if (pending) { + for_each_set_bit(offset, &pending, gpio->ngpio[0]) { +- int gpio_irq = irq_find_mapping(gc->irq.domain, +- offset); +- generic_handle_irq(gpio_irq); +- +- if ((irq_get_trigger_type(gpio_irq) & +- IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) +- phytium_gpio_toggle_trigger(gpio, offset); ++ if (index == -1 || offset == index) { ++ int gpio_irq = irq_find_mapping(gc->irq.domain, ++ offset); ++ generic_handle_irq(gpio_irq); ++ if ((irq_get_trigger_type(gpio_irq) & ++ IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) ++ phytium_gpio_toggle_trigger(gpio, offset); ++ } + } + } + +@@ -347,9 +365,17 @@ EXPORT_SYMBOL_GPL(phytium_gpio_get_direction); + int + phytium_gpio_irq_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) + { ++ int hwirq = irqd_to_hwirq(d); + struct gpio_chip *chip_data = irq_data_get_irq_chip_data(d); +- struct irq_chip *chip = irq_get_chip(*(chip_data->irq.parents)); +- struct irq_data *data = irq_get_irq_data(*(chip_data->irq.parents)); ++ struct irq_chip *chip; ++ struct irq_data *data; ++ ++ if ((chip_data->irq.num_parents) == 1) ++ hwirq = 0; ++ ++ chip = irq_get_chip(chip_data->irq.parents[hwirq]); ++ data = irq_get_irq_data(chip_data->irq.parents[hwirq]); ++ + + if (chip && chip->irq_set_affinity) + return chip->irq_set_affinity(data, mask_val, force); +diff --git a/drivers/gpio/gpio-phytium-core.h b/drivers/gpio/gpio-phytium-core.h +index d45a9ab11944..f09a081cfdf2 100644 +--- a/drivers/gpio/gpio-phytium-core.h ++++ b/drivers/gpio/gpio-phytium-core.h +@@ -64,6 +64,7 @@ struct phytium_gpio { + struct irq_chip irq_chip; + unsigned int ngpio[2]; + int irq[32]; ++ int is_resuming; + #ifdef CONFIG_PM_SLEEP + struct phytium_gpio_ctx ctx; + #endif +diff --git a/drivers/gpio/gpio-phytium-pci.c b/drivers/gpio/gpio-phytium-pci.c +index e68772dd7a88..0f94fb5b5e96 100644 +--- a/drivers/gpio/gpio-phytium-pci.c ++++ b/drivers/gpio/gpio-phytium-pci.c +@@ -64,9 +64,13 @@ static int phytium_gpio_pci_probe(struct pci_dev *pdev, const struct pci_device_ + gpio->irq_chip.irq_set_type = phytium_gpio_irq_set_type; + gpio->irq_chip.irq_enable = phytium_gpio_irq_enable; + gpio->irq_chip.irq_disable = phytium_gpio_irq_disable; ++ gpio->irq_chip.irq_set_affinity = phytium_gpio_irq_set_affinity; + + raw_spin_lock_init(&gpio->lock); + ++ writel(0, gpio->regs + GPIO_INTEN); ++ writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); ++ + gpio->gc.base = -1; + gpio->gc.get_direction = phytium_gpio_get_direction; + gpio->gc.direction_input = phytium_gpio_direction_input; +@@ -77,6 +81,7 @@ static int phytium_gpio_pci_probe(struct pci_dev *pdev, const struct pci_device_ + gpio->gc.label = dev_name(dev); + gpio->gc.parent = dev; + gpio->gc.owner = THIS_MODULE; ++ gpio->is_resuming = 0; + + girq = &gpio->gc.irq; + girq->handler = handle_bad_irq; +@@ -128,11 +133,13 @@ static int phytium_gpio_pci_suspend(struct device *dev) + gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB); + + gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN); ++ gpio->is_resuming = 1; + gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK); + gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); + gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY); + gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE); + ++ writel(0, gpio->regs + GPIO_INTEN); + raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +@@ -153,7 +160,6 @@ static int phytium_gpio_pci_resume(struct device *dev) + writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR); + writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB); + +- writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); + writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK); + writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL); + writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY); +@@ -161,6 +167,9 @@ static int phytium_gpio_pci_resume(struct device *dev) + + writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); + ++ writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); ++ gpio->is_resuming = 0; ++ + raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +diff --git a/drivers/gpio/gpio-phytium-platform.c b/drivers/gpio/gpio-phytium-platform.c +index 9fe3191f789d..e80fab7c8151 100644 +--- a/drivers/gpio/gpio-phytium-platform.c ++++ b/drivers/gpio/gpio-phytium-platform.c +@@ -87,6 +87,9 @@ static int phytium_gpio_probe(struct platform_device *pdev) + #endif + raw_spin_lock_init(&gpio->lock); + ++ writel(0, gpio->regs + GPIO_INTEN); ++ writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); ++ + gpio->gc.base = -1; + gpio->gc.get_direction = phytium_gpio_get_direction; + gpio->gc.direction_input = phytium_gpio_direction_input; +@@ -97,6 +100,7 @@ static int phytium_gpio_probe(struct platform_device *pdev) + gpio->gc.label = dev_name(dev); + gpio->gc.parent = dev; + gpio->gc.owner = THIS_MODULE; ++ gpio->is_resuming = 0; + + girq = &gpio->gc.irq; + girq->handler = handle_bad_irq; +@@ -145,11 +149,13 @@ static int phytium_gpio_suspend(struct device *dev) + gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB); + + gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN); ++ gpio->is_resuming = 1; + gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK); + gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); + gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY); + gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE); + ++ writel(0, gpio->regs + GPIO_INTEN); + raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +@@ -170,7 +176,6 @@ static int phytium_gpio_resume(struct device *dev) + writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR); + writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB); + +- writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); + writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK); + writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL); + writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY); +@@ -178,6 +183,9 @@ static int phytium_gpio_resume(struct device *dev) + + writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); + ++ writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); ++ gpio->is_resuming = 0; ++ + raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +diff --git a/drivers/gpu/drm/phytium/pe220x_dc.h b/drivers/gpu/drm/phytium/pe220x_dc.h +index 1fd0db3b8d3f..8902d1134850 100644 +--- a/drivers/gpu/drm/phytium/pe220x_dc.h ++++ b/drivers/gpu/drm/phytium/pe220x_dc.h +@@ -9,8 +9,8 @@ + #define __PE220X_DC_H__ + + #define PE220X_DC_PIX_CLOCK_MAX (594000) +-#define PE220X_DC_HDISPLAY_MAX 3840 +-#define PE220X_DC_VDISPLAY_MAX 2160 ++#define PE220X_DC_HDISPLAY_MAX 1920 ++#define PE220X_DC_VDISPLAY_MAX 1080 + #define PE220X_DC_ADDRESS_MASK 0x7f + + extern void pe220x_dc_hw_vram_init(struct phytium_display_private *priv, +diff --git a/drivers/gpu/drm/phytium/phytium_crtc.c b/drivers/gpu/drm/phytium/phytium_crtc.c +index 2e932418d981..16f68a4deeeb 100644 +--- a/drivers/gpu/drm/phytium/phytium_crtc.c ++++ b/drivers/gpu/drm/phytium/phytium_crtc.c +@@ -600,6 +600,12 @@ phytium_crtc_atomic_enable(struct drm_crtc *crtc, + else + phytium_crtc_gamma_init(crtc); + ++ /* enable dither*/ ++ DRM_DEBUG_KMS("Enable dither on DC-%d\n", phys_pipe); ++ phytium_writel_reg(priv, DITHER_TABLE_LOW, group_offset, DC_DITHER_TABLE_LOW); ++ phytium_writel_reg(priv, DITHER_TABLE_HIGH, group_offset, DC_DITHER_TABLE_HIGH); ++ phytium_writel_reg(priv, ENABLE, group_offset, DC_DITHER_CONFIG); ++ + phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG); + drm_crtc_vblank_on(crtc); + } +diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c +index 3f0084610fb1..9cb88830dfc8 100644 +--- a/drivers/gpu/drm/phytium/phytium_display_drv.c ++++ b/drivers/gpu/drm/phytium/phytium_display_drv.c +@@ -345,6 +345,7 @@ struct drm_driver phytium_display_drm_driver = { + .irq_uninstall = phytium_irq_uninstall, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_free_object_unlocked = phytium_gem_free_object, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_import_sg_table = phytium_gem_prime_import_sg_table, +diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c +index cc1e2d2ae78d..978a4b1a753f 100644 +--- a/drivers/gpu/drm/phytium/phytium_dp.c ++++ b/drivers/gpu/drm/phytium/phytium_dp.c +@@ -1735,6 +1735,7 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s + enum drm_connector_status status = connector->status; + bool video_enable = false; + uint32_t index = 0; ++ struct edid *edid = NULL; + + if (phytium_dp->is_edp) + status = connector_status_connected; +@@ -1768,6 +1769,15 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s + mdelay(2); + phytium_dp_hw_enable_video(phytium_dp); + } ++ ++ edid = drm_get_edid(connector, &phytium_dp->aux.ddc); ++ ++ if (edid && drm_edid_is_valid(edid)) ++ phytium_dp->has_audio = drm_detect_monitor_audio(edid); ++ else ++ phytium_dp->has_audio = false; ++ ++ kfree(edid); + } + + out: +diff --git a/drivers/gpu/drm/phytium/phytium_reg.h b/drivers/gpu/drm/phytium/phytium_reg.h +index f5d4a6945c35..14a481090679 100644 +--- a/drivers/gpu/drm/phytium/phytium_reg.h ++++ b/drivers/gpu/drm/phytium/phytium_reg.h +@@ -29,6 +29,12 @@ + #define PANEL_DATAENABLE_ENABLE (1<<0) + #define PANEL_DATA_ENABLE (1<<4) + #define PANEL_CLOCK_ENABLE (1<<8) ++#define DC_DITHER_CONFIG 0X1410 ++ #define ENABLE 0x80000000 ++#define DC_DITHER_TABLE_LOW 0x1420 ++ #define DITHER_TABLE_LOW 0x7B48F3C0 ++#define DC_DITHER_TABLE_HIGH 0X1428 ++ #define DITHER_TABLE_HIGH 0x596AD1E2 + #define PHYTIUM_DC_HDISPLAY 0x1430 + #define HDISPLAY_END_SHIFT 0 + #define HDISPLAY_END_MASK 0x7fff +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index c2bdd7b92ec7..76b3fcf2d173 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -1234,6 +1234,8 @@ config I2C_PHYTIUM_PLATFORM + This driver can also be built as a module. If so, the module + will be called i2c-phytium-platform. + ++source "drivers/i2c/busses/phytium_i2c_v2/Kconfig" ++ + comment "External I2C/SMBus adapter drivers" + + config I2C_DIOLAN_U2C +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index 78372fb6587a..a94ccad30209 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -124,7 +124,7 @@ obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o + obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o + obj-$(CONFIG_I2C_ZX2967) += i2c-zx2967.o + obj-$(CONFIG_I2C_PHYTIUM_CORE) += i2c-phytium-core.o +-i2c-phytium-core-objs := i2c-phytium-common.o i2c-phytium-master.o i2c-phytium-slave.o ++i2c-phytium-core-objs := i2c-phytium-common.o i2c-phytium-mix.o + obj-$(CONFIG_I2C_PHYTIUM_PCI) += i2c-phytium-pci.o + obj-$(CONFIG_I2C_PHYTIUM_PLATFORM) += i2c-phytium-platform.o + +@@ -152,5 +152,5 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o + obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o + obj-$(CONFIG_SCx200_ACB) += scx200_acb.o + obj-$(CONFIG_I2C_FSI) += i2c-fsi.o +- ++obj-$(CONFIG_I2C_V2_PLATFORM) += phytium_i2c_v2/ + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/busses/i2c-phytium-common.c b/drivers/i2c/busses/i2c-phytium-common.c +index 810871d455ad..e21e02cce4e1 100644 +--- a/drivers/i2c/busses/i2c-phytium-common.c ++++ b/drivers/i2c/busses/i2c-phytium-common.c +@@ -2,8 +2,6 @@ + /* + * Phytium I2C adapter driver. + * +- * Based on the TI DAVINCI I2C adapter driver. +- * + * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. + */ + #include +@@ -17,6 +15,7 @@ + #include + #include + #include ++#include + + #include "i2c-phytium-core.h" + +@@ -93,22 +92,7 @@ int i2c_phytium_set_sda_hold(struct phytium_i2c_dev *dev) + + void __i2c_phytium_disable(struct phytium_i2c_dev *dev) + { +- int timeout = 100; +- +- do { +- __i2c_phytium_disable_nowait(dev); +- if ((phytium_readl(dev, IC_ENABLE_STATUS) & 1) == 0) +- return; +- +- /* +- * Wait 10 times the signaling period of the highest I2C +- * transfer supported by the driver (for 400KHz this is +- * 25us). +- */ +- usleep_range(25, 250); +- } while (timeout--); +- +- dev_warn(dev->dev, "timeout in disabling adapter\n"); ++ __i2c_phytium_disable_nowait(dev); + } + + unsigned long i2c_phytium_clk_rate(struct phytium_i2c_dev *dev) +@@ -131,23 +115,12 @@ int i2c_phytium_prepare_clk(struct phytium_i2c_dev *dev, bool prepare) + } + EXPORT_SYMBOL_GPL(i2c_phytium_prepare_clk); + +-int i2c_phytium_wait_bus_not_busy(struct phytium_i2c_dev *dev) ++int i2c_phytium_check_bus_not_busy(struct phytium_i2c_dev *dev) + { +- int timeout = 20; /* 20 ms */ +- +- while (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) { +- if (timeout <= 0) { +- dev_warn(dev->dev, "timeout waiting for bus ready\n"); +- i2c_recover_bus(&dev->adapter); +- +- if (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) +- return -ETIMEDOUT; +- return 0; +- } +- timeout--; +- usleep_range(1000, 1100); +- } +- ++ if (dev->slave_state != SLAVE_STATE_IDLE) ++ return -EAGAIN; ++ if (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) ++ return -ETIMEDOUT; + return 0; + } + +diff --git a/drivers/i2c/busses/i2c-phytium-core.h b/drivers/i2c/busses/i2c-phytium-core.h +index 726b6b509d52..0b9f3c741992 100644 +--- a/drivers/i2c/busses/i2c-phytium-core.h ++++ b/drivers/i2c/busses/i2c-phytium-core.h +@@ -8,9 +8,13 @@ + #include + #include + #include ++#include ++ ++#define I2C_PHYTIUM_DRV_VERSION "1.0.0" + + #define IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ + I2C_FUNC_SMBUS_BYTE | \ ++ I2C_FUNC_SMBUS_QUICK | \ + I2C_FUNC_SMBUS_BYTE_DATA | \ + I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_BLOCK_DATA | \ +@@ -88,7 +92,6 @@ + #define IC_INTR_SMBALERT_IN_N 0x20000 + + #define IC_INTR_DEFAULT_MASK (IC_INTR_RX_FULL | \ +- IC_INTR_TX_ABRT | \ + IC_INTR_STOP_DET) + #define IC_INTR_MASTER_MASK (IC_INTR_DEFAULT_MASK | \ + IC_INTR_TX_EMPTY) +@@ -99,7 +102,8 @@ + #define IC_INTR_SMBUS_MASK (IC_INTR_MASTER_MASK | \ + IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | \ + IC_INTR_SMBCLK_TMO_LOW_TIMEOUT | \ +- IC_INTR_SMBSDA_LOW_TIMEOUT) ++ IC_INTR_SMBSDA_LOW_TIMEOUT | \ ++ IC_INTR_SMBALERT_IN_N) + + #define IC_STATUS_ACTIVITY 0x1 + #define IC_STATUS_TFE BIT(2) +@@ -110,6 +114,15 @@ + #define IC_SDA_HOLD_RX_MASK GENMASK(23, IC_SDA_HOLD_RX_SHIFT) + + #define IC_ERR_TX_ABRT 0x1 ++#define IC_ERR_SMBLK_READ_ZERO BIT(31) ++ ++#define IC_ENABLE_EN BIT(0) ++#define IC_ENABLE_ALERT_EN BIT(5) ++#define IC_ENABLE_RXDATA_ADVANCE_EN BIT(11) ++#define IC_ENABLE_MASK (IC_ENABLE_EN | \ ++ IC_ENABLE_ALERT_EN | \ ++ IC_ENABLE_RXDATA_ADVANCE_EN) ++#define IC_DISABLE_MASK IC_ENABLE_ALERT_EN + + #define IC_TAR_10BITADDR_MASTER BIT(12) + +@@ -126,6 +139,15 @@ + #define PHYTIUM_IC_MASTER 0 + #define PHYTIUM_IC_SLAVE 1 + ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++enum i2c_slave_state { ++ SLAVE_STATE_IDLE, ++ SLAVE_STATE_RECV, ++ SLAVE_STATE_SEND, ++ SLAVE_STATE_REQUEST, ++ SLAVE_STATE_RESPONSE ++}; ++#endif + #define ABRT_7B_ADDR_NOACK 0 + #define ABRT_10ADDR1_NOACK 1 + #define ABRT_10ADDR2_NOACK 2 +@@ -173,6 +195,12 @@ struct phytium_i2c_dev { + struct clk *clk; + struct reset_control *rst; + int mode; ++ ++ u32 capability; ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ enum i2c_slave_state slave_state; ++#endif ++ spinlock_t i2c_lock; + struct i2c_client *slave; + u32 (*get_clk_rate_khz)(struct phytium_i2c_dev *dev); + +@@ -215,6 +243,7 @@ struct phytium_i2c_dev { + u16 hs_lcnt; + + bool pm_disabled; ++ bool first_time_init_master; + void (*disable)(struct phytium_i2c_dev *dev); + void (*disable_int)(struct phytium_i2c_dev *dev); + int (*init)(struct phytium_i2c_dev *dev); +@@ -228,7 +257,7 @@ u32 phytium_readl(struct phytium_i2c_dev *dev, int offset); + void phytium_writel(struct phytium_i2c_dev *dev, u32 b, int offset); + unsigned long i2c_phytium_clk_rate(struct phytium_i2c_dev *dev); + int i2c_phytium_prepare_clk(struct phytium_i2c_dev *dev, bool prepare); +-int i2c_phytium_wait_bus_not_busy(struct phytium_i2c_dev *dev); ++int i2c_phytium_check_bus_not_busy(struct phytium_i2c_dev *dev); + int i2c_phytium_handle_tx_abort(struct phytium_i2c_dev *dev); + u32 i2c_phytium_func(struct i2c_adapter *adap); + void i2c_phytium_disable(struct phytium_i2c_dev *dev); +@@ -239,16 +268,14 @@ u32 i2c_phytium_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); + + static inline void __i2c_phytium_enable(struct phytium_i2c_dev *dev) + { +- phytium_writel(dev, 1, IC_ENABLE); ++ phytium_writel(dev, IC_ENABLE_MASK, IC_ENABLE); + } + + static inline void __i2c_phytium_disable_nowait(struct phytium_i2c_dev *dev) + { +- phytium_writel(dev, 0, IC_ENABLE); ++ phytium_writel(dev, IC_DISABLE_MASK, IC_ENABLE); + } + + void __i2c_phytium_disable(struct phytium_i2c_dev *dev); +- ++void i2c_phytium_configure_master(struct phytium_i2c_dev *dev); + extern int i2c_phytium_probe(struct phytium_i2c_dev *dev); +- +-extern int i2c_phytium_probe_slave(struct phytium_i2c_dev *dev); +diff --git a/drivers/i2c/busses/i2c-phytium-master.c b/drivers/i2c/busses/i2c-phytium-mix.c +similarity index 51% +rename from drivers/i2c/busses/i2c-phytium-master.c +rename to drivers/i2c/busses/i2c-phytium-mix.c +index b8bf2612fdda..748042c9feb6 100644 +--- a/drivers/i2c/busses/i2c-phytium-master.c ++++ b/drivers/i2c/busses/i2c-phytium-mix.c +@@ -4,6 +4,7 @@ + * + * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. + */ ++#include + #include + #include + #include +@@ -17,6 +18,78 @@ + + #include "i2c-phytium-core.h" + ++#define I2C_TRANS_READ_CMD BIT(8) ++#define I2C_TRANS_STOP_CMD BIT(9) ++#define I2C_TRANS_RESTART_CMD BIT(10) ++#define I2C_QUICK_CMD_BIT_SET BIT(13) ++#define DEFAULT_TIMEOUT (DEFAULT_CLOCK_FREQUENCY / 1000 * 35) ++ ++static int i2c_phytium_recover_controller(struct phytium_i2c_dev *dev) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->i2c_lock, flags); ++ ++ reset_control_reset(dev->rst); ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ dev->slave_state = SLAVE_STATE_IDLE; ++ dev->status = STATUS_IDLE; ++ if (dev->slave) ++ phytium_writel(dev, dev->slave->addr, IC_SAR); ++#endif ++ ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); ++ return 0; ++} ++ ++static int i2c_phytium_init_slave(struct phytium_i2c_dev *dev) ++{ ++ /* Disable the adapter. */ ++ __i2c_phytium_disable(dev); ++ ++ /* Write SDA hold time if supported */ ++ if (dev->sda_hold_time) ++ phytium_writel(dev, dev->sda_hold_time, IC_SDA_HOLD); ++ ++ /* Configure Tx/Rx FIFO threshold levels. */ ++ phytium_writel(dev, 0, IC_TX_TL); ++ phytium_writel(dev, 0, IC_RX_TL); ++ dev->mode = PHYTIUM_IC_SLAVE; ++ ++ /* Configure the I2C slave. */ ++ dev->slave_cfg = IC_CON_RX_FIFO_FULL_HLD_CTRL | IC_CON_RESTART_EN | ++ IC_CON_STOP_DET_IFADDRESSED; ++ phytium_writel(dev, dev->slave_cfg, IC_CON); ++ phytium_writel(dev, IC_INTR_SLAVE_MASK, IC_INTR_MASK); ++ ++ return 0; ++} ++ ++void i2c_phytium_configure_master(struct phytium_i2c_dev *dev) ++{ ++ struct i2c_timings *t = &dev->timings; ++ ++ dev->functionality = I2C_FUNC_10BIT_ADDR | IC_DEFAULT_FUNCTIONALITY | ++ I2C_FUNC_SLAVE; ++ ++ dev->master_cfg = ++ IC_CON_MASTER | IC_CON_SLAVE_DISABLE | IC_CON_RESTART_EN; ++ ++ dev->mode = PHYTIUM_IC_MASTER; ++ ++ switch (t->bus_freq_hz) { ++ case 100000: ++ dev->master_cfg |= IC_CON_SPEED_STD; ++ break; ++ case 3400000: ++ dev->master_cfg |= IC_CON_SPEED_HIGH; ++ break; ++ default: ++ dev->master_cfg |= IC_CON_SPEED_FAST; ++ } ++} ++EXPORT_SYMBOL_GPL(i2c_phytium_configure_master); ++ + static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) + { + /* Disable the adapter */ +@@ -35,7 +108,7 @@ static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) + phytium_writel(dev, dev->hs_hcnt, IC_HS_SCL_HCNT); + phytium_writel(dev, dev->hs_lcnt, IC_HS_SCL_LCNT); + } +- ++ dev->mode = PHYTIUM_IC_MASTER; + /* Write SDA hold time if supported */ + if (dev->sda_hold_time) + phytium_writel(dev, dev->sda_hold_time, IC_SDA_HOLD); +@@ -45,11 +118,29 @@ static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) + phytium_writel(dev, 0, IC_RX_TL); + + /* Configure the I2C master */ ++ if (dev->first_time_init_master == false) { ++ i2c_phytium_configure_master(dev); ++ dev->first_time_init_master = true; ++ } + phytium_writel(dev, dev->master_cfg, IC_CON); + + return 0; + } + ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++static void i2c_phytium_change_mode(int target_mode, struct phytium_i2c_dev *dev) ++{ ++ if (target_mode == PHYTIUM_IC_MASTER) { ++ dev->disable_int(dev); ++ dev->disable(dev); ++ i2c_phytium_init_master(dev); ++ } else { ++ i2c_phytium_init_slave(dev); ++ __i2c_phytium_enable(dev); ++ } ++} ++#endif ++ + static void i2c_phytium_xfer_init(struct phytium_i2c_dev *dev) + { + struct i2c_msg *msgs = dev->msgs; +@@ -58,6 +149,9 @@ static void i2c_phytium_xfer_init(struct phytium_i2c_dev *dev) + /* Disable the adapter */ + __i2c_phytium_disable(dev); + ++ if ((dev->capability & I2C_FUNC_SMBUS_QUICK) && (msgs[0].len == 0)) ++ ic_tar = I2C_QUICK_CMD_BIT_SET; ++ + /* If the slave address is 10-bit address, enable 10BITADDR */ + ic_con = phytium_readl(dev, IC_CON); + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { +@@ -99,23 +193,26 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) + u8 *buf = dev->tx_buf; + bool need_restart = false; + +- intr_mask = IC_INTR_MASTER_MASK; ++ intr_mask = IC_INTR_SMBUS_MASK; + + for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { + u32 flags = msgs[dev->msg_write_idx].flags; + + if (msgs[dev->msg_write_idx].addr != addr) { +- dev_err(dev->dev, +- "%s: invalid target address\n", __func__); + dev->msg_err = -EINVAL; + break; + } ++ /* If the register dose not support smbus block read function, ++ * then use the operation of program code ++ */ ++ if (!(dev->capability & I2C_FUNC_SMBUS_BLOCK_DATA) && ++ (flags & I2C_M_RECV_LEN)) ++ msgs[dev->msg_write_idx].len = 1 + I2C_SMBUS_BLOCK_MAX; + + if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { + /* new i2c_msg */ + buf = msgs[dev->msg_write_idx].buf; + buf_len = msgs[dev->msg_write_idx].len; +- + if ((dev->master_cfg & IC_CON_RESTART_EN) && + (dev->msg_write_idx > 0)) + need_restart = true; +@@ -123,16 +220,14 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) + + tx_limit = dev->tx_fifo_depth - phytium_readl(dev, IC_TXFLR); + rx_limit = dev->tx_fifo_depth - phytium_readl(dev, IC_RXFLR); +- + while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { + u32 cmd = 0; + +- if (dev->msg_write_idx == dev->msgs_num - 1 && +- buf_len == 1 && !(flags & I2C_M_RECV_LEN)) +- cmd |= BIT(9); ++ if (dev->msg_write_idx == dev->msgs_num - 1 && buf_len == 1) ++ cmd |= I2C_TRANS_STOP_CMD; + + if (need_restart) { +- cmd |= BIT(10); ++ cmd |= I2C_TRANS_RESTART_CMD; + need_restart = false; + } + +@@ -141,7 +236,7 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) + if (dev->rx_outstanding >= dev->rx_fifo_depth) + break; + +- phytium_writel(dev, cmd | 0x100, IC_DATA_CMD); ++ phytium_writel(dev, cmd | I2C_TRANS_READ_CMD, IC_DATA_CMD); + rx_limit--; + dev->rx_outstanding++; + } else { +@@ -159,13 +254,21 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) + * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop + * the transaction here. + */ +- if (buf_len > 0 || flags & I2C_M_RECV_LEN) { ++ if (buf_len > 0) { + /* more bytes to be written */ + dev->status |= STATUS_WRITE_IN_PROGRESS; + break; +- } else { +- dev->status &= ~STATUS_WRITE_IN_PROGRESS; + } ++ dev->status &= ~STATUS_WRITE_IN_PROGRESS; ++ } ++ ++ /*This is use for quick cmd*/ ++ if ((dev->capability & I2C_FUNC_SMBUS_QUICK) && (msgs[0].len == 0)) { ++ if (msgs[0].flags == I2C_M_RD) ++ phytium_writel(dev, I2C_TRANS_STOP_CMD | I2C_TRANS_READ_CMD, ++ IC_DATA_CMD); ++ else ++ phytium_writel(dev, I2C_TRANS_STOP_CMD, IC_DATA_CMD); + } + + if (dev->msg_write_idx == dev->msgs_num) +@@ -174,7 +277,7 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) + if (dev->msg_err) + intr_mask = 0; + +- phytium_writel(dev, intr_mask, IC_INTR_MASK); ++ phytium_writel(dev, intr_mask, IC_INTR_MASK); + } + + static u8 i2c_phytium_recv_len(struct phytium_i2c_dev *dev, u8 len) +@@ -186,10 +289,17 @@ static u8 i2c_phytium_recv_len(struct phytium_i2c_dev *dev, u8 len) + * Adjust the buffer length and mask the flag + * after receiving the first byte. + */ ++ if (len > I2C_SMBUS_BLOCK_MAX) ++ len = 0; ++ + len += (flags & I2C_CLIENT_PEC) ? 2 : 1; + dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding); +- msgs[dev->msg_read_idx].len = len; +- msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN; ++ ++ /* require adding one byte to trigger the i2c_phytium_xfer finishing the transaction. */ ++ if (dev->tx_buf_len == 0) { ++ dev->tx_buf_len = 1; ++ len = dev->rx_outstanding + 1; ++ } + + return len; + } +@@ -221,9 +331,19 @@ static void i2c_phytium_read(struct phytium_i2c_dev *dev) + + *buf = phytium_readl(dev, IC_DATA_CMD); + /* Ensure length byte is a valid value */ +- if (flags & I2C_M_RECV_LEN && +- *buf <= I2C_SMBUS_BLOCK_MAX && *buf > 0) { ++ if (flags & I2C_M_RECV_LEN) { ++ msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN; + len = i2c_phytium_recv_len(dev, *buf); ++ if (*buf > I2C_SMBUS_BLOCK_MAX || *buf == 0) { ++ dev_err(dev->dev, ++ "The value %d is out of the SMBus range [1~32]\n", ++ *buf); ++ *buf = 0; ++ dev->cmd_err = IC_ERR_SMBLK_READ_ZERO; ++ } else { ++ msgs[dev->msg_read_idx].len = *buf + ++ ((flags & I2C_CLIENT_PEC) ? 2 : 1); ++ } + } + buf++; + dev->rx_outstanding--; +@@ -234,21 +354,29 @@ static void i2c_phytium_read(struct phytium_i2c_dev *dev) + dev->rx_buf_len = len; + dev->rx_buf = buf; + return; +- } else +- dev->status &= ~STATUS_READ_IN_PROGRESS; ++ } ++ dev->status &= ~STATUS_READ_IN_PROGRESS; + } + } + +-static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) ++static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], ++ int num) + { + struct phytium_i2c_dev *dev = i2c_get_adapdata(adapter); + int ret; ++ unsigned long flags; + + dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); + +- pm_runtime_get_sync(dev->dev); ++ ret = pm_runtime_get_sync(dev->dev); ++ if (ret < 0) { ++ dev_err(dev->dev, "pm runtime get sync err.\n"); ++ goto pm_exit; ++ } + ++ spin_lock_irqsave(&dev->i2c_lock, flags); + reinit_completion(&dev->cmd_complete); ++ + dev->msgs = msgs; + dev->msgs_num = num; + dev->cmd_err = 0; +@@ -259,22 +387,30 @@ static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], + dev->abort_source = 0; + dev->rx_outstanding = 0; + +- ret = i2c_phytium_wait_bus_not_busy(dev); ++ ret = i2c_phytium_check_bus_not_busy(dev); + if (ret < 0) + goto done; + ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ if (dev->slave_cfg) ++ i2c_phytium_change_mode(PHYTIUM_IC_MASTER, dev); ++#endif ++ + /* Start the transfers */ + i2c_phytium_xfer_init(dev); +- ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); + /* Wait for tx to complete */ +- if (!wait_for_completion_timeout(&dev->cmd_complete, adapter->timeout)) { ++ if (!wait_for_completion_timeout(&dev->cmd_complete, ++ adapter->timeout)) { + dev_err(dev->dev, "controller timed out\n"); +- i2c_recover_bus(&dev->adapter); +- i2c_phytium_init_master(dev); ++ i2c_phytium_recover_controller(dev); ++ spin_lock_irqsave(&dev->i2c_lock, flags); ++ if (!dev->slave_cfg) ++ i2c_phytium_init_master(dev); + ret = -ETIMEDOUT; + goto done; + } +- ++ spin_lock_irqsave(&dev->i2c_lock, flags); + __i2c_phytium_disable_nowait(dev); + + if (dev->msg_err) { +@@ -289,29 +425,99 @@ static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], + + /* We have got an error */ + if (dev->cmd_err == IC_ERR_TX_ABRT) { ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); + ret = i2c_phytium_handle_tx_abort(dev); ++ spin_lock_irqsave(&dev->i2c_lock, flags); + goto done; + } + +- if (dev->status) +- dev_err(dev->dev, "transfer terminated early.\n"); +- + ret = -EIO; + + done: ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ if (dev->slave_cfg) ++ i2c_phytium_change_mode(PHYTIUM_IC_SLAVE, dev); ++ dev->status = STATUS_IDLE; ++ dev->slave_state = SLAVE_STATE_IDLE; ++#endif ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); ++ ++pm_exit: ++ + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + + return ret; + } + ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++static int i2c_phytium_reg_slave(struct i2c_client *slave) ++{ ++ int ret = 0; ++ unsigned long flags; ++ struct phytium_i2c_dev *dev = i2c_get_adapdata(slave->adapter); ++ ++ spin_lock_irqsave(&dev->i2c_lock, flags); ++ ++ if (dev->slave) { ++ ret = -EBUSY; ++ goto abort; ++ } ++ if (slave->flags & I2C_CLIENT_TEN) { ++ ret = -EAFNOSUPPORT; ++ goto abort; ++ } ++ pm_runtime_get_sync(dev->dev); ++ ++ /* ++ * Set slave address in the IC_SAR register, ++ * the address to which the i2c responds. ++ */ ++ i2c_phytium_init_slave(dev); ++ phytium_writel(dev, slave->addr, IC_SAR); ++ dev->slave = slave; ++ dev->mode = PHYTIUM_IC_SLAVE; ++ __i2c_phytium_enable(dev); ++ ++ dev->cmd_err = 0; ++ dev->msg_write_idx = 0; ++ dev->msg_read_idx = 0; ++ dev->msg_err = 0; ++ dev->status = STATUS_IDLE; ++ dev->abort_source = 0; ++ dev->rx_outstanding = 0; ++ ++abort: ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); ++ return ret; ++} ++ ++static int i2c_phytium_unreg_slave(struct i2c_client *slave) ++{ ++ unsigned long flags; ++ struct phytium_i2c_dev *dev = i2c_get_adapdata(slave->adapter); ++ ++ spin_lock_irqsave(&dev->i2c_lock, flags); ++ ++ dev->disable_int(dev); ++ dev->disable(dev); ++ dev->slave = NULL; ++ pm_runtime_put(dev->dev); ++ ++ dev->mode = PHYTIUM_IC_MASTER; ++ i2c_phytium_init_master(dev); ++ spin_unlock_irqrestore(&dev->i2c_lock, flags); ++ return 0; ++} ++#endif ++ + static const struct i2c_algorithm i2c_phytium_algo = { + .master_xfer = i2c_phytium_xfer, + .functionality = i2c_phytium_func, +-}; +- +-static const struct i2c_adapter_quirks i2c_phytium_quirks = { +- .flags = I2C_AQ_NO_ZERO_LEN, ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ .reg_slave = i2c_phytium_reg_slave, ++ .unreg_slave = i2c_phytium_unreg_slave, ++#endif + }; + + static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) +@@ -329,7 +535,8 @@ static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) + if (stat & IC_INTR_RD_REQ) + phytium_readl(dev, IC_CLR_RD_REQ); + if (stat & IC_INTR_TX_ABRT) { +- dev->abort_source = phytium_readl(dev, IC_TX_ABRT_SOURCE); ++ if (dev->mode == PHYTIUM_IC_MASTER) ++ dev->abort_source = phytium_readl(dev, IC_TX_ABRT_SOURCE); + phytium_readl(dev, IC_CLR_TX_ABRT); + } + if (stat & IC_INTR_RX_DONE) +@@ -356,12 +563,14 @@ static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) + + static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) + { +- u32 stat; ++ u32 stat, raw_stat; + ++ raw_stat = phytium_readl(dev, IC_RAW_INTR_STAT); + stat = i2c_phytium_read_clear_intrbits(dev); + + /* SMBus interrupt */ +- if (stat & (IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | IC_INTR_SMBCLK_TMO_LOW_TIMEOUT)) { ++ if (stat & ++ (IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | IC_INTR_SMBCLK_TMO_LOW_TIMEOUT)) { + phytium_writel(dev, phytium_readl(dev, IC_ENABLE) & (~BIT(6)), + IC_ENABLE); + phytium_writel(dev, phytium_readl(dev, IC_ENABLE) | BIT(4), +@@ -378,15 +587,25 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) + if (stat & IC_INTR_SMBALERT_IN_N && dev->ara) + i2c_handle_smbus_alert(dev->ara); + +- if (stat & IC_INTR_TX_ABRT) { +- dev->cmd_err |= IC_ERR_TX_ABRT; +- dev->status = STATUS_IDLE; +- +- /* Anytime TX_ABRT is set, the contents of the tx/rx +- * buffers are flushed. Make sure to skip them. +- */ +- phytium_writel(dev, 0, IC_INTR_MASK); +- goto abort; ++ if (raw_stat & IC_INTR_TX_ABRT) { ++ if (stat & IC_INTR_TX_ABRT) { ++ dev->cmd_err |= IC_ERR_TX_ABRT; ++ dev->status = STATUS_IDLE; ++ ++ /* Anytime TX_ABRT is set, the contents of the tx/rx ++ * buffers are flushed. Make sure to skip them. ++ */ ++ phytium_writel(dev, 0, IC_INTR_MASK); ++ goto abort; ++ } else if (stat & IC_INTR_STOP_DET) { ++ dev->cmd_err |= IC_ERR_TX_ABRT; ++ dev->status = STATUS_IDLE; ++ phytium_readl(dev, IC_CLR_TX_ABRT); ++ phytium_writel(dev, 0, IC_INTR_MASK); ++ ++ complete(&dev->cmd_complete); ++ return 0; ++ } + } + + if (stat & IC_INTR_RX_FULL) +@@ -396,10 +615,9 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) + i2c_phytium_xfer_msg(dev); + + abort: +- if ((stat & (IC_INTR_TX_ABRT | IC_INTR_STOP_DET)) || +- dev->msg_err) ++ if ((stat & IC_INTR_TX_ABRT) || (stat & IC_INTR_STOP_DET) || dev->msg_err) { + complete(&dev->cmd_complete); +- else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { ++ } else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { + /* Workaround to trigger pending interrupt */ + stat = phytium_readl(dev, IC_INTR_MASK); + i2c_phytium_disable_int(dev); +@@ -409,6 +627,93 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) + return 0; + } + ++static int i2c_phytium_irq_handler_slave(struct phytium_i2c_dev *dev) ++{ ++ u32 raw_stat, stat, enabled; ++ u8 val, slave_activity; ++ ++ enabled = phytium_readl(dev, IC_ENABLE); ++ raw_stat = phytium_readl(dev, IC_RAW_INTR_STAT); ++ slave_activity = ++ ((phytium_readl(dev, IC_STATUS) & IC_STATUS_SLAVE_ACTIVITY) >> ++ 6); ++ ++ if (!enabled || !(raw_stat & ~IC_INTR_ACTIVITY) || !dev->slave) ++ return 0; ++ ++ stat = i2c_phytium_read_clear_intrbits(dev); ++ ++ if (stat & IC_INTR_RX_FULL) { ++ if (dev->status != STATUS_WRITE_IN_PROGRESS) { ++ dev->status = STATUS_WRITE_IN_PROGRESS; ++ i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, ++ &val); ++ dev->slave_state = SLAVE_STATE_RECV; ++ } ++ do { ++ val = phytium_readl(dev, IC_DATA_CMD); ++ i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, ++ &val); ++ val = phytium_readl(dev, IC_STATUS); ++ } while (val & BIT(3)); ++ } ++ ++ if (stat & IC_INTR_RD_REQ) { ++ if (slave_activity) { ++ phytium_readl(dev, IC_CLR_RD_REQ); ++ ++ if (!(dev->status & STATUS_READ_IN_PROGRESS)) { ++ i2c_slave_event(dev->slave, ++ I2C_SLAVE_READ_REQUESTED, &val); ++ dev->status |= STATUS_READ_IN_PROGRESS; ++ dev->status &= ~STATUS_WRITE_IN_PROGRESS; ++ dev->slave_state = SLAVE_STATE_SEND; ++ ++ } else { ++ i2c_slave_event(dev->slave, ++ I2C_SLAVE_READ_PROCESSED, &val); ++ } ++ phytium_writel(dev, val, IC_DATA_CMD); ++ } ++ } ++ ++ if (stat & IC_INTR_STOP_DET) { ++ i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ dev->status = STATUS_IDLE; ++ dev->slave_state = SLAVE_STATE_IDLE; ++#endif ++ } ++ ++ return 1; ++} ++ ++static irqreturn_t i2c_phytium_isr(int this_irq, void *dev_id) ++{ ++ struct phytium_i2c_dev *dev = dev_id; ++ u32 stat, enabled; ++ ++ spin_lock(&dev->i2c_lock); ++ ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ if (dev->mode == PHYTIUM_IC_SLAVE) { ++ i2c_phytium_irq_handler_slave(dev); ++ spin_unlock(&dev->i2c_lock); ++ return IRQ_HANDLED; ++ } ++#endif ++ enabled = phytium_readl(dev, IC_ENABLE); ++ stat = phytium_readl(dev, IC_RAW_INTR_STAT); ++ if (!enabled || !(stat & ~IC_INTR_ACTIVITY)) { ++ spin_unlock(&dev->i2c_lock); ++ return IRQ_NONE; ++ } ++ ++ i2c_phytium_irq_handler_master(dev); ++ spin_unlock(&dev->i2c_lock); ++ return IRQ_HANDLED; ++} ++ + static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) + { + const char *mode_str, *fp_str = ""; +@@ -424,24 +729,21 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) + /* Calculate SCL timing parameters for standard mode if not set */ + if (!dev->ss_hcnt || !dev->ss_lcnt) { + ic_clk = i2c_phytium_clk_rate(dev); +- dev->ss_hcnt = +- i2c_phytium_scl_hcnt(ic_clk, +- 4000, /* tHD;STA = tHIGH = 4.0 us */ +- sda_falling_time, +- 0, /* 0: DW default, 1: Ideal */ +- 0); /* No offset */ ++ dev->ss_hcnt = i2c_phytium_scl_hcnt( ++ ic_clk, 4000, /* tHD;STA = tHIGH = 4.0 us */ ++ sda_falling_time, 0, /* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ + dev->ss_lcnt = +- i2c_phytium_scl_lcnt(ic_clk, +- 4700, /* tLOW = 4.7 us */ +- scl_falling_time, +- 0); /* No offset */ ++ i2c_phytium_scl_lcnt(ic_clk, 4700, /* tLOW = 4.7 us */ ++ scl_falling_time, ++ 0); /* No offset */ + } +- dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", +- dev->ss_hcnt, dev->ss_lcnt); ++ dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", dev->ss_hcnt, ++ dev->ss_lcnt); + /* + * Set SCL timing parameters for fast mode or fast mode plus. Only +- * difference is the timing parameter values since the registers are +- * the same. ++ * difference is the timing parameter values since the registers ++ * are the same. + */ + if (t->bus_freq_hz == 1000000) { + /* +@@ -460,20 +762,17 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) + */ + if (!dev->fs_hcnt || !dev->fs_lcnt) { + ic_clk = i2c_phytium_clk_rate(dev); +- dev->fs_hcnt = +- i2c_phytium_scl_hcnt(ic_clk, +- 600, /* tHD;STA = tHIGH = 0.6 us */ +- sda_falling_time, +- 0, /* 0: DW default, 1: Ideal */ +- 0); /* No offset */ ++ dev->fs_hcnt = i2c_phytium_scl_hcnt( ++ ic_clk, 600, /* tHD;STA = tHIGH = 0.6 us */ ++ sda_falling_time, 0, /* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ + dev->fs_lcnt = +- i2c_phytium_scl_lcnt(ic_clk, +- 1300, /* tLOW = 1.3 us */ +- scl_falling_time, +- 0); /* No offset */ ++ i2c_phytium_scl_lcnt(ic_clk, 1300, /* tLOW = 1.3 us */ ++ scl_falling_time, ++ 0); /* No offset */ + } +- dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", +- fp_str, dev->fs_hcnt, dev->fs_lcnt); ++ dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", fp_str, ++ dev->fs_hcnt, dev->fs_lcnt); + + if (dev->hs_hcnt && dev->hs_lcnt) + dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", +@@ -499,19 +798,18 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) + return ret; + } + +-static irqreturn_t i2c_phytium_isr(int this_irq, void *dev_id) ++static int i2c_phytium_enable_smbus_alert(struct phytium_i2c_dev *i2c_dev) + { +- struct phytium_i2c_dev *dev = dev_id; +- u32 stat, enabled; ++ struct i2c_adapter *adap = &i2c_dev->adapter; ++ struct i2c_smbus_alert_setup setup; + +- enabled = phytium_readl(dev, IC_ENABLE); +- stat = phytium_readl(dev, IC_RAW_INTR_STAT); +- if (!enabled || !(stat & ~IC_INTR_ACTIVITY)) +- return IRQ_NONE; ++ setup.irq = 0; ++ i2c_dev->ara = i2c_new_smbus_alert_device(adap, &setup); + +- i2c_phytium_irq_handler_master(dev); ++ if (IS_ERR(i2c_dev->ara)) ++ return PTR_ERR(i2c_dev->ara); + +- return IRQ_HANDLED; ++ return 0; + } + + int i2c_phytium_probe(struct phytium_i2c_dev *dev) +@@ -519,13 +817,21 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) + struct i2c_adapter *adapter = &dev->adapter; + unsigned long irq_flags; + int ret; ++ u32 alert = 0; + + init_completion(&dev->cmd_complete); ++ if (dev->mode == PHYTIUM_IC_MASTER) { ++ snprintf(adapter->name, sizeof(adapter->name), ++ "Phytium I2C Adapter"); ++ dev->init = i2c_phytium_init_master; ++ } else if (dev->mode == PHYTIUM_IC_SLAVE) { ++ snprintf(adapter->name, sizeof(adapter->name), ++ "Phytium I2C Slave Adapter"); ++ dev->init = i2c_phytium_init_slave; ++ } + +- dev->init = i2c_phytium_init_master; + dev->disable = i2c_phytium_disable; + dev->disable_int = i2c_phytium_disable_int; +- + ret = i2c_phytium_set_timings_master(dev); + if (ret) + return ret; +@@ -534,16 +840,14 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) + if (ret) + return ret; + +- /* XXX: should be initialized in firmware, remove it in future */ +-#define DEFAULT_TIMEOUT (DEFAULT_CLOCK_FREQUENCY / 1000 * 35) +- phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_MEXT); +- phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_TIMEOUT); +- phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBDAT_STUCK_TIMEOUT); ++ if (dev->mode == PHYTIUM_IC_MASTER) { ++ phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_MEXT); ++ phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_TIMEOUT); ++ phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBDAT_STUCK_TIMEOUT); ++ } + +- snprintf(adapter->name, sizeof(adapter->name), "Phytium I2C adapter"); + adapter->retries = 3; + adapter->algo = &i2c_phytium_algo; +- adapter->quirks = &i2c_phytium_quirks; + adapter->dev.parent = dev->dev; + i2c_set_adapdata(adapter, dev); + +@@ -553,7 +857,8 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) + ret = devm_request_irq(dev->dev, dev->irq, i2c_phytium_isr, irq_flags, + dev_name(dev->dev), dev); + if (ret) { +- dev_err(dev->dev, "failed to request irq %i: %d\n", dev->irq, ret); ++ dev_err(dev->dev, "failed to request irq %i: %d\n", dev->irq, ++ ret); + return ret; + } + +@@ -567,11 +872,27 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) + ret = i2c_add_numbered_adapter(adapter); + if (ret) + dev_err(dev->dev, "fail to add adapter: %d\n", ret); ++ ++ if (of_property_read_bool(dev->dev->of_node, "smbus-alert")) ++ alert = 1; ++ else if (has_acpi_companion(dev->dev)) ++ fwnode_property_read_u32_array(dev->dev->fwnode, "smbus_alert", &alert, 1); ++ ++ if (alert) { ++ ret = i2c_phytium_enable_smbus_alert(dev); ++ if (ret) { ++ dev_err(dev->dev, ++ "failed to enable SMBus alert protocol (%d)\n", ret); ++ } ++ } ++ + pm_runtime_put_noidle(dev->dev); + + return ret; + } + EXPORT_SYMBOL_GPL(i2c_phytium_probe); + +-MODULE_DESCRIPTION("Phytium I2C bus master adapter"); ++MODULE_AUTHOR("Wu Jinyong "); ++MODULE_DESCRIPTION("Phytium I2C bus controller adapter"); + MODULE_LICENSE("GPL"); ++MODULE_VERSION(I2C_PHYTIUM_DRV_VERSION); +diff --git a/drivers/i2c/busses/i2c-phytium-pci.c b/drivers/i2c/busses/i2c-phytium-pci.c +index d2639afc0c1a..34ca0a863ba1 100644 +--- a/drivers/i2c/busses/i2c-phytium-pci.c ++++ b/drivers/i2c/busses/i2c-phytium-pci.c +@@ -174,6 +174,10 @@ static int i2c_phytium_pci_probe(struct pci_dev *pdev, + dev->irq = pdev->irq; + dev->flags |= controller->flags; + ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ dev->slave_state = SLAVE_STATE_IDLE; ++#endif ++ spin_lock_init(&dev->i2c_lock); + dev->functionality = controller->functionality | IC_DEFAULT_FUNCTIONALITY; + dev->master_cfg = controller->bus_cfg; + if (controller->scl_sda_cfg) { +@@ -196,6 +200,8 @@ static int i2c_phytium_pci_probe(struct pci_dev *pdev, + ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev)); + adapter->nr = controller->bus_num; + ++ dev->capability = 0; ++ dev->first_time_init_master = true; + ret = i2c_phytium_probe(dev); + if (ret) + goto out; +diff --git a/drivers/i2c/busses/i2c-phytium-platform.c b/drivers/i2c/busses/i2c-phytium-platform.c +index d9160c428c24..f33aeb32cb25 100644 +--- a/drivers/i2c/busses/i2c-phytium-platform.c ++++ b/drivers/i2c/busses/i2c-phytium-platform.c +@@ -64,9 +64,7 @@ static int phytium_i2c_acpi_configure(struct platform_device *pdev) + struct phytium_i2c_dev *dev = platform_get_drvdata(pdev); + struct i2c_timings *t = &dev->timings; + u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0; +- acpi_handle handle = ACPI_HANDLE(&pdev->dev); + const struct acpi_device_id *id; +- struct acpi_device *adev; + + dev->adapter.nr = -1; + dev->tx_fifo_depth = 32; +@@ -101,9 +99,6 @@ static int phytium_i2c_acpi_configure(struct platform_device *pdev) + if (id && id->driver_data) + dev->flags |= (u32)id->driver_data; + +- if (acpi_bus_get_device(handle, &adev)) +- return -ENODEV; +- + return 0; + } + +@@ -119,29 +114,6 @@ static inline int phytium_i2c_acpi_configure(struct platform_device *pdev) + } + #endif + +-static void i2c_phytium_configure_master(struct phytium_i2c_dev *dev) +-{ +- struct i2c_timings *t = &dev->timings; +- +- dev->functionality = I2C_FUNC_10BIT_ADDR | IC_DEFAULT_FUNCTIONALITY; +- +- dev->master_cfg = IC_CON_MASTER | IC_CON_SLAVE_DISABLE | +- IC_CON_RESTART_EN; +- +- dev->mode = PHYTIUM_IC_MASTER; +- +- switch (t->bus_freq_hz) { +- case 100000: +- dev->master_cfg |= IC_CON_SPEED_STD; +- break; +- case 3400000: +- dev->master_cfg |= IC_CON_SPEED_HIGH; +- break; +- default: +- dev->master_cfg |= IC_CON_SPEED_FAST; +- } +-} +- + static void i2c_phytium_configure_slave(struct phytium_i2c_dev *dev) + { + dev->functionality = I2C_FUNC_SLAVE | IC_DEFAULT_FUNCTIONALITY; +@@ -180,6 +152,11 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) + + dev->dev = &pdev->dev; + dev->irq = irq; ++ dev->first_time_init_master = false; ++#if IS_ENABLED(CONFIG_I2C_SLAVE) ++ dev->slave_state = SLAVE_STATE_IDLE; ++#endif ++ spin_lock_init(&dev->i2c_lock); + platform_set_drvdata(pdev, dev); + + dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); +@@ -231,11 +208,12 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) + goto exit_reset; + } + +- if (i2c_detect_slave_mode(&pdev->dev)) ++ if (i2c_detect_slave_mode(&pdev->dev)) { + i2c_phytium_configure_slave(dev); +- else ++ } else { ++ dev->first_time_init_master = true; + i2c_phytium_configure_master(dev); +- ++ } + dev->clk = devm_clk_get(&pdev->dev, NULL); + if (!i2c_phytium_prepare_clk(dev, true)) { + u64 clk_khz; +@@ -257,6 +235,9 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) + adap->class = I2C_CLASS_DEPRECATED; + ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); + adap->dev.of_node = pdev->dev.of_node; ++ adap->dev.fwnode = pdev->dev.fwnode; ++ ++ dev->capability = 0; + + dev_pm_set_driver_flags(&pdev->dev, + DPM_FLAG_SMART_PREPARE | +@@ -272,10 +253,7 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) + + pm_runtime_enable(&pdev->dev); + +- if (dev->mode == PHYTIUM_IC_SLAVE) +- ret = i2c_phytium_probe_slave(dev); +- else +- ret = i2c_phytium_probe(dev); ++ ret = i2c_phytium_probe(dev); + + if (ret) + goto exit_probe; +diff --git a/drivers/i2c/busses/phytium_i2c_v2/Kconfig b/drivers/i2c/busses/phytium_i2c_v2/Kconfig +new file mode 100644 +index 000000000000..c08fd8f9f0e3 +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/Kconfig +@@ -0,0 +1,16 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Sensor device configuration ++# ++ ++config I2C_V2_PLATFORM ++ tristate "Phytium I2C_V2 Platform" ++ depends on (ACPI && COMMON_CLK) || !ACPI ++ select I2C_SMBUS ++ ++ help ++ If you say yes to this option, support will be included for the ++ Phytium I2C adapter. Only master mode is supported. ++ ++ This driver can also be built as a module.If so,the module ++ will be called i2c-phytium-v2-platform. +diff --git a/drivers/i2c/busses/phytium_i2c_v2/Makefile b/drivers/i2c/busses/phytium_i2c_v2/Makefile +new file mode 100644 +index 000000000000..74161298d7c8 +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/Makefile +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for the i2c bus drivers. ++# ++ ++obj-$(CONFIG_I2C_V2_PLATFORM) += i2c-phytium-v2-platform.o ++i2c-phytium-v2-platform-objs := i2c-phyt-platform.o i2c-phyt-common.o i2c-phyt-master.o i2c-phyt-slave.o +diff --git a/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-common.c b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-common.c +new file mode 100644 +index 000000000000..f9fe6d876b60 +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-common.c +@@ -0,0 +1,512 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Phytium I2C adapter driver. ++ * ++ * Copyright (C) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "i2c-phyt-core.h" ++ ++#define FT_LOG_LINE_MAX_LEN 400 ++#define FT_LOG_MAX_SIZE 8192 ++ ++static void i2c_phyt_send_msg(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *set_msg, bool complete_flag); ++ ++static char *i2c_ft_abort_sources[] = { ++ [FT_I2C_TIMEOUT] = "I2C cmd not acknowledged", ++ [FT_I2C_CNT_ERR] = "I2C timings count error", ++ [FT_I2C_TX_ABRT] = "Tx abort", ++ [FT_I2C_INT_ERR] = "Interrupt error", ++ [FT_I2C_BLOCK_SIZE] = "smbus block error", ++ [FT_I2C_INVALID_ADDR] = "slave address invalid", ++ [FT_I2C_CHECK_STATUS_ERR] = "Uncomplete status", ++}; ++ ++u32 i2c_phyt_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) ++{ ++ if (cond) ++ return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; ++ else ++ return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000 - 3 + offset; ++} ++ ++u32 i2c_phyt_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) ++{ ++ return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; ++} ++ ++unsigned long i2c_phyt_clk_rate(struct i2c_phyt_dev *dev) ++{ ++ if (WARN_ON_ONCE(!dev->get_clk_rate_khz)) ++ return 0; ++ ++ return dev->get_clk_rate_khz(dev); ++} ++ ++int i2c_phyt_prepare_clk(struct i2c_phyt_dev *dev, bool prepare) ++{ ++ if (IS_ERR(dev->clk)) ++ return PTR_ERR(dev->clk); ++ ++ if (prepare) ++ return clk_prepare_enable(dev->clk); ++ ++ clk_disable_unprepare(dev->clk); ++ ++ return 0; ++} ++ ++void i2c_phyt_handle_tx_abort(struct i2c_phyt_dev *dev) ++{ ++ unsigned long abort_source = dev->abort_source; ++ int i; ++ ++ for_each_set_bit(i, &abort_source, ARRAY_SIZE(i2c_ft_abort_sources)) ++ dev_info(dev->dev, "%s: %s\n", __func__, i2c_ft_abort_sources[i]); ++} ++ ++u32 i2c_phyt_func(struct i2c_adapter *adapter) ++{ ++ struct i2c_phyt_dev *dev = i2c_get_adapdata(adapter); ++ ++ return dev->functionality; ++} ++ ++void i2c_phyt_common_watchdog(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, ++ reg | FT_I2C_REGFILE_HEARTBIT_VAL); ++} ++ ++void i2c_phyt_enable_alive(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, ++ reg | FT_I2C_REGFILE_HEARTBIT_VAL); ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, ++ reg | FT_I2C_LOG_ADDR_LOG_ALIVE); ++} ++ ++void i2c_phyt_disable_alive(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ reg &= ~FT_I2C_LOG_ADDR_LOG_ALIVE; ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, reg); ++} ++ ++void i2c_phyt_enable_debug(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, ++ reg | FT_I2C_LOG_ADDR_LOG_DEBUG); ++} ++ ++void i2c_phyt_disable_debug(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ reg &= ~FT_I2C_LOG_ADDR_LOG_DEBUG; ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, reg); ++} ++ ++ ++void i2c_phyt_show_log(struct i2c_phyt_dev *dev) ++{ ++ u32 i, reg, len; ++ u8 *plog; ++ ++ if (!dev->log_addr) ++ return; ++ ++ /*set lock*/ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, ++ reg | FT_I2C_LOG_ADDR_LOCK_VAL); ++ ++ plog = dev->log_addr; ++ if (reg & FT_I2C_LOG_ADDR_LOG_FLAG) { ++ len = strnlen((char *)dev->log_addr, FT_LOG_MAX_SIZE); ++ dev_info(dev->dev, "log len :%d,addr: 0x%llx,size:%d\n", len, (u64)dev->log_addr, ++ dev->log_size); ++ if (len > FT_LOG_LINE_MAX_LEN) { ++ for (i = 0; i + FT_LOG_LINE_MAX_LEN < len; i += FT_LOG_LINE_MAX_LEN) ++ dev_info(dev->dev, "(log)%.*s\n", FT_LOG_LINE_MAX_LEN, &plog[i]); ++ } else { ++ dev_info(dev->dev, "(log)%.*s\n", FT_LOG_LINE_MAX_LEN, &plog[0]); ++ } ++ ++ for (i = 0; i < dev->log_size; i++) ++ plog[i] = 0; ++ } ++ /*clear log flag*/ ++ reg &= ~FT_I2C_LOG_ADDR_LOG_FLAG; ++ /*unset lock*/ ++ reg &= ~FT_I2C_LOG_ADDR_LOCK_VAL; ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_DEBUG, reg); ++} ++ ++int i2c_phyt_malloc_log_mem(struct i2c_phyt_dev *dev) ++{ ++ u32 reg; ++ u64 phy_addr; ++ ++ reg = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_DEBUG); ++ phy_addr = ((reg & FT_I2C_LOG_ADDR_MASK) >> FT_I2C_LOG_ADDR_LOW_SHIFT) << ++ FT_I2C_LOG_ADDR_SHIFT; ++ dev->log_size = ((reg & FT_I2C_LOG_SIZE_MASK) >> FT_I2C_LOG_SIZE_LOW_SHIFT) * 1024; ++ ++ dev->log_addr = devm_ioremap(dev->dev, phy_addr, dev->log_size); ++ ++ if (IS_ERR(dev->log_addr)) { ++ dev_err(dev->dev, "log_addr is err\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++void i2c_phyt_common_regfile_disable_int(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_MASK, ++ FT_I2C_REGFILE_DISABLE_INTR_VAL); ++} ++ ++void i2c_phyt_common_regfile_enable_int(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_MASK, ++ FT_I2C_REGFILE_ENABLE_INTR_VAL); ++} ++ ++void i2c_phyt_common_regfile_clear_rv2ap_int(struct i2c_phyt_dev *dev, ++ u32 stat) ++{ ++ /*For Desktop type,this opt is useful*/ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_STAT, ++ stat & ~FT_I2C_RV2AP_INTR_BIT4); ++ /*For Service type,this opt is useful*/ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_CLEAR, ++ stat | FT_I2C_RV2AP_INTR_BIT4); ++} ++ ++void i2c_phyt_common_set_cmd(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *i2c_mng_msg, u8 cmd, u8 sub_cmd) ++{ ++ i2c_mng_msg->head.cmd_type = cmd; ++ i2c_mng_msg->head.cmd_subid = sub_cmd; ++ i2c_mng_msg->head.status0 = FT_I2C_MSG_COMPLETE_UNKNOWN; ++} ++ ++void i2c_phyt_set_cmd8(struct i2c_phyt_dev *dev, ++ u8 sub_cmd, u8 data) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_SET, sub_cmd); ++ i2c_mng_msg.data[0] = data; ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++void i2c_phyt_set_cmd16(struct i2c_phyt_dev *dev, ++ u8 sub_cmd, u16 data) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ u16 *ctrl = (u16 *)&i2c_mng_msg.data[0]; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_SET, sub_cmd); ++ *ctrl = data; ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++void i2c_phyt_set_cmd32(struct i2c_phyt_dev *dev, ++ u8 sub_cmd, u32 data) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ u32 *cmd_data = (u32 *)&i2c_mng_msg.data[0]; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_SET, sub_cmd); ++ *cmd_data = data; ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++void i2c_phyt_data_cmd8_array(struct i2c_phyt_dev *dev, ++ u8 sub_cmd, u8 *data, int len) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ /*set cmd*/ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_DATA, sub_cmd); ++ /*set data*/ ++ memcpy(&i2c_mng_msg.data[0], &data[0], len); ++ /*set len*/ ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, false); ++} ++ ++void i2c_phyt_default_cfg(struct i2c_phyt_dev *dev, ++ struct i2c_ft_default_cfg_msg *buf) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_DEFAULT, ++ PHYTI2C_MSG_CMD_DEFAULT_RESUME); ++ memcpy(&i2c_mng_msg.data[0], (char *)buf, sizeof(struct i2c_ft_default_cfg_msg)); ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++void i2c_phyt_disable_int(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_set_cmd32(dev, PHYTI2C_MSG_CMD_SET_INTERRUPT, 0); ++} ++ ++void i2c_phyt_trig_rv_intr(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_AP2RV_INTR_STATE, ++ FT_I2C_REGFILE_AP2RV_SET_INTR_VAL); ++} ++ ++static void i2c_phyt_send_msg(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *set_msg, bool complete_flag) ++{ ++ u64 *p_dest_msg = (u64 *)dev->tx_shmem_addr; ++ u64 *p_src_msg = (u64 *)set_msg; ++ int i, len; ++ ++ if (complete_flag) { ++ reinit_completion(&dev->cmd_complete); ++ dev->complete_flag = true; ++ dev->mng.is_need_check = false; ++ } ++ len = DIV_ROUND_UP(dev->total_shmem_len, 8); ++ ++ for (i = 0; i < len; i++) ++ p_dest_msg[i] = p_src_msg[i]; ++ /*For config cmd,no use tail and head,set this value to zero*/ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_TAIL, 0); ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_HEAD, 0); ++ dev->mng.tx_cmd_cnt = 1; ++ dev->mng.cur_cmd_cnt = 0; ++ i2c_phyt_trig_rv_intr(dev); ++} ++ ++void i2c_phyt_notify_rv(struct i2c_phyt_dev *dev, ++ bool need_check) ++{ ++ reinit_completion(&dev->cmd_complete); ++ dev->complete_flag = true; ++ ++ dev->mng.is_need_check = need_check; ++ i2c_phyt_trig_rv_intr(dev); ++} ++ ++void i2c_phyt_set_suspend(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_set_cmd32(dev, PHYTI2C_MSG_CMD_SET_SUSPEND, 0); ++ ++ if (i2c_phyt_check_result(dev)) ++ dev_warn(dev->dev, "fail to set suspend\n"); ++} ++ ++void i2c_phyt_set_sda_hold(struct i2c_phyt_dev *dev, u32 data) ++{ ++ i2c_phyt_set_cmd32(dev, PHYTI2C_MSG_CMD_SET_SDA_HOLD, data); ++} ++ ++int i2c_phyt_check_status(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *msg) ++{ ++ int result = FT_I2C_CHECK_STATUS_ERR; ++ ++ dev->abort_source = 1 << FT_I2C_CHECK_STATUS_ERR; ++ /* RV Has update the result,but not sure the result is OK*/ ++ if (msg->head.status0 != FT_I2C_MSG_COMPLETE_UNKNOWN) { ++ if (!dev->mng.is_need_check || ++ ((msg->head.status0 == FT_I2C_MSG_COMPLETE_OK) && ++ (msg->head.status1 == FT_I2C_SUCCESS))) { ++ dev->abort_source = 0; ++ result = FT_I2C_SUCCESS; ++ } else { ++ i2c_phyt_show_log(dev); ++ dev->abort_source = 1 << msg->head.status1; ++ } ++ } ++ ++ return result; ++} ++ ++int i2c_phyt_check_result(struct i2c_phyt_dev *dev) ++{ ++ if (!wait_for_completion_timeout(&dev->cmd_complete, ++ dev->adapter.timeout)) { ++ dev_err(dev->dev, "check timed out\n"); ++ i2c_phyt_show_log(dev); ++ dev->abort_source = BIT(FT_I2C_TIMEOUT); ++ return -EINVAL; ++ } ++ if (!dev->abort_source) ++ return 0; ++ return -EINVAL; ++} ++ ++void i2c_phyt_disable(struct i2c_phyt_dev *dev) ++{ ++ i2c_phyt_set_module_en(dev, FT_I2C_ADAPTER_MODULE_OFF); ++ ++ i2c_phyt_check_result(dev); ++} ++ ++void i2c_phyt_set_module_en(struct i2c_phyt_dev *dev, u8 data) ++{ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_MODULE_EN, data); ++} ++ ++void i2c_phyt_set_int_tl(struct i2c_phyt_dev *dev, ++ u8 tx_threshold, u8 rx_threshold) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ struct i2c_phyt_fifo_threshold *ctrl = ++ (struct i2c_phyt_fifo_threshold *)&i2c_mng_msg.data[0]; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_SET, ++ PHYTI2C_MSG_CMD_SET_INT_TL); ++ ++ ctrl->tx_fifo_threshold = tx_threshold; ++ ctrl->rx_fifo_threshold = rx_threshold; ++ ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++void i2c_phyt_set_int_interrupt(struct i2c_phyt_dev *dev, ++ u32 is_enable, u32 intr_mask) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ u32 *data = (u32 *)i2c_mng_msg.data; ++ ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_phyt_common_set_cmd(dev, &i2c_mng_msg, PHYTI2C_MSG_CMD_SET, ++ PHYTI2C_MSG_CMD_SET_INTERRUPT); ++ ++ data[0] = is_enable; ++ data[1] = intr_mask; ++ dev->total_shmem_len = FT_I2C_MSG_CMDDATA_SIZE; ++ ++ i2c_phyt_send_msg(dev, &i2c_mng_msg, true); ++} ++ ++static int i2c_phyt_report_cmd_handle(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *rx_msg, u32 head, u32 tail) ++{ ++ u16 sub_cmd = rx_msg->head.cmd_subid; ++ int ret = -EINVAL; ++ ++ switch (sub_cmd) { ++ case PHYTI2C_MSG_CMD_SLAVE_EVENT: ++ ret = i2c_phyt_slave_event_process(dev, rx_msg, head, tail); ++ break; ++ case PHYTI2C_MSG_CMD_SMBALERT_IN_N: ++ ret = i2c_phyt_master_smbus_alert_process(dev); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++void i2c_phyt_slave_isr_handle(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info *rx_msg = (struct phyt_msg_info *)dev->rx_shmem_addr; ++ struct phyt_msg_info msg_buf; ++ u32 head, tail; ++ ++ tail = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_TAIL); ++ head = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_HEAD); ++ ++ /*There is only one rx_msg*/ ++ memcpy(&msg_buf, &rx_msg[0], sizeof(msg_buf)); ++ ++ if (msg_buf.head.cmd_type == PHYTI2C_MSG_CMD_REPORT) ++ i2c_phyt_report_cmd_handle(dev, &msg_buf, head, tail); ++} ++ ++static void i2c_phyt_set_complete(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info *set_msg = (struct phyt_msg_info *)dev->rx_shmem_addr; ++ struct phyt_msg_info tmp_msg; ++ ++ /*There is only one rx_msg*/ ++ memcpy(&tmp_msg, &set_msg[0], sizeof(struct phyt_msg_info)); ++ tmp_msg.head.status0 = FT_I2C_MSG_COMPLETE_OK; ++ tmp_msg.head.cmd_type = 0xff; ++ tmp_msg.head.cmd_subid = 0xff; ++ memcpy(&set_msg[0], &tmp_msg, sizeof(struct phyt_msg_info)); ++} ++ ++void i2c_phyt_master_isr_handle(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info *rx_msg = (struct phyt_msg_info *)dev->rx_shmem_addr; ++ struct phyt_msg_info msg_buf; ++ ++ memcpy(&msg_buf, &rx_msg[0], sizeof(struct phyt_msg_info)); ++ i2c_phyt_set_complete(dev); ++ ++ if (msg_buf.head.cmd_type == PHYTI2C_MSG_CMD_REPORT) ++ i2c_phyt_report_cmd_handle(dev, &msg_buf, 0, 0); ++} ++ ++MODULE_AUTHOR("Wu Jinyong "); ++MODULE_DESCRIPTION("Phytium I2C bus adapter core"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-core.h b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-core.h +new file mode 100644 +index 000000000000..1ed19d20d2c3 +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-core.h +@@ -0,0 +1,512 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Phytium I2C adapter driver. ++ * ++ * Copyright (C) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++#ifndef I2C_PHYT_CORE_H__ ++#define I2C_PHYT_CORE_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define I2C_PHYTIUM_V2_DRV_VERSION "1.0.2" ++ ++#define FT_I2C_MSG_UNIT_SIZE 10 ++#define FT_I2C_DATA_RESV_LEN 2 ++#define FT_I2C_SHMEM_RX_ADDR_OFFSET 384 ++#define FT_I2C_MSG_CMDDATA_SIZE 64 ++#define FT_I2C_IN_INTERRUPT_MODE 0 ++#define FT_I2C_ENABLE_INTERRUPT 1 ++#define FT_I2C_REGFILE_AP2RV_INTR_MASK 0x20 ++#define FT_I2C_REGFILE_AP2RV_INTR_STATE 0x24 ++#define FT_I2C_REGFILE_RV2AP_INTR_MASK 0x28 ++#define FT_I2C_REGFILE_RV2AP_INTR_STAT 0x2C ++#define FT_I2C_REGFILE_RING 0x48 ++#define FT_I2C_REGFILE_DEBUG 0x58 ++#define FT_I2C_REGFILE_RV2AP_INTR_CLEAR 0x74 ++#define FT_I2C_TRANS_FRAME_START (BIT(0)) ++#define FT_I2C_TRANS_FRAME_END (BIT(1)) ++#define FT_I2C_TRANS_FRAME_RESTART (BIT(2)) ++#define FT_I2C_REGFILE_TX_RING_OFFSET 8 ++#define FT_I2C_REGFILE_TX_RING_MASK GENMASK(13, 8) ++ ++#define FT_I2C_REGFILE_HEARTBIT_VAL BIT(2) ++#define FT_I2C_LOG_SIZE_LOW_SHIFT 4 ++#define FT_I2C_LOG_SIZE_MASK GENMASK(7, FT_I2C_LOG_SIZE_LOW_SHIFT) ++#define FT_I2C_LOG_ADDR_SHIFT 10 ++#define FT_I2C_LOG_ADDR_LOW_SHIFT 8 ++#define FT_I2C_LOG_ADDR_MASK GENMASK(29, FT_I2C_LOG_ADDR_LOW_SHIFT) ++#define FT_I2C_LOG_ADDR_LOCK_VAL BIT(31) ++#define FT_I2C_LOG_ADDR_LOG_FLAG BIT(3) ++#define FT_I2C_LOG_ADDR_LOG_ALIVE BIT(1) ++#define FT_I2C_LOG_ADDR_LOG_DEBUG BIT(0) ++#define FT_I2C_REGFILE_DISABLE_INTR_VAL GENMASK(31, 0) ++#define FT_I2C_REGFILE_ENABLE_INTR_VAL 0 ++#define FT_I2C_REGFILE_AP2RV_SET_INTR_VAL BIT(4) ++ ++#define FT_I2C_RV2AP_INTR_BIT4 BIT(4) ++ ++#define FT_I2C_ADAPTER_MODULE_ON 1 ++#define FT_I2C_ADAPTER_MODULE_OFF 2 ++#define FT_I2C_ADAPTER_MODULE_RESET 3 ++ ++#define FT_I2C_BUS_SPEED_STANARD_MODE 1 ++#define FT_I2C_BUS_SPEED_FAST_MODE 2 ++#define FT_I2C_BUS_SPEED_HIGH_MODE 3 ++#define FT_I2C_BUS_SPEED_TRANS_PARAM_MODE 0 ++#define FT_I2C_BUS_SPEED_CALC_MODE 1 ++ ++#define FT_I2C_REGFILE_TX_HEAD 0 ++#define FT_I2C_REGFILE_TX_TAIL 0x04 ++#define FT_I2C_REGFILE_HEAD 0x08 ++#define FT_I2C_REGFILE_TAIL 0x0C ++ ++#define FT_IC_DEFAULT_FUNCTIONALITY \ ++ (I2C_FUNC_I2C | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |\ ++ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |\ ++ I2C_FUNC_SMBUS_I2C_BLOCK) ++ ++#define FT_I2C_VIRT_RV_SHMEM_TX_MSG_MAX_CNT 1 ++ ++#define FT_I2C_MASTER_MODE_FLAG 1 ++#define FT_I2C_SLAVE_MODE_FLAG 0 ++ ++#define FT_I2C_RESTART_FLAG 1 ++#define FT_I2C_NOT_RESTART_FLAG 0 ++ ++#define FT_I2C_SLAVE_DATA_IN 0 ++#define FT_I2C_SLAVE_DATA_OUT 1 ++ ++#define FT_I2C_SPEED_100K 100000 ++#define FT_I2C_SPEED_400K 400000 ++#define FT_I2C_SPEED_1000K 1000000 ++#define FT_I2C_SPEED_3400K 3400000 ++ ++#define FT_IC_CON_MASTER 0x1 ++#define FT_IC_CON_SPEED_STD 0x2 ++#define FT_IC_CON_SPEED_FAST 0x4 ++#define FT_IC_CON_SPEED_HIGH 0x6 ++#define FT_IC_CON_SPEED_MASK 0x6 ++#define FT_IC_CON_10BITADDR_SLAVE 0x8 ++#define FT_IC_CON_10BITADDR_MASTER 0x10 ++#define FT_IC_CON_RESTART_EN 0x20 ++#define FT_IC_CON_SLAVE_DISABLE 0x40 ++#define FT_IC_CON_STOP_DET_IFADDRESSED 0x80 ++#define FT_I2C_CON_STOP_DET_IFADDR_MASK 0x80 ++#define FT_IC_CON_TX_EMPTY_CTRL 0x100 ++#define FT_IC_CON_RX_FIFO_FULL_HLD_CTRL 0x200 ++#define FT_I2C_CON_RX_FIFO_FULL_HLD_MASK 0x200 ++ ++#define FT_IC_CON 0x0 ++#define FT_IC_TAR 0x4 ++#define FT_IC_SAR 0x8 ++#define FT_IC_DATA_CMD 0x10 ++#define FT_IC_SS_SCL_HCNT 0x14 ++#define FT_IC_SS_SCL_LCNT 0x18 ++#define FT_IC_FS_SCL_HCNT 0x1c ++#define FT_IC_FS_SCL_LCNT 0x20 ++#define FT_IC_HS_SCL_HCNT 0x24 ++#define FT_IC_HS_SCL_LCNT 0x28 ++#define FT_IC_INTR_STAT 0x2c ++#define FT_IC_INTR_MASK 0x30 ++#define FT_IC_RAW_INTR_STAT 0x34 ++#define FT_IC_RX_TL 0x38 ++#define FT_IC_TX_TL 0x3c ++#define FT_IC_CLR_INTR 0x40 ++#define FT_IC_CLR_RX_UNDER 0x44 ++#define FT_IC_CLR_RX_OVER 0x48 ++#define FT_IC_CLR_TX_OVER 0x4c ++#define FT_IC_CLR_RD_REQ 0x50 ++#define FT_IC_CLR_TX_ABRT 0x54 ++#define FT_IC_CLR_RX_DONE 0x58 ++#define FT_IC_CLR_ACTIVITY 0x5c ++#define FT_IC_CLR_STOP_DET 0x60 ++#define FT_IC_CLR_START_DET 0x64 ++#define FT_IC_CLR_GEN_CALL 0x68 ++#define FT_IC_ENABLE 0x6c ++#define FT_IC_STATUS 0x70 ++#define FT_IC_TXFLR 0x74 ++#define FT_IC_RXFLR 0x78 ++#define FT_IC_SDA_HOLD 0x7c ++#define FT_IC_TX_ABRT_SOURCE 0x80 ++#define FT_IC_ENABLE_STATUS 0x9c ++#define FT_IC_SMBCLK_LOW_MEXT 0xa8 ++#define FT_IC_SMBCLK_LOW_TIMEOUT 0xac ++#define FT_IC_SMBDAT_STUCK_TIMEOUT 0xb4 ++#define FT_IC_CLR_SMBCLK_EXT_LOW_TIMEOUT 0xbc ++#define FT_IC_CLR_SMBCLK_TMO_LOW_TIMEOUT 0xc0 ++#define FT_IC_CLR_SMBDAT_LOW_TIMEOUT 0xc4 ++#define FT_IC_CLR_SMBALERT_IN_N 0xd0 ++ ++#define FT_IC_INTR_RX_UNDER 0x001 ++#define FT_IC_INTR_RX_OVER 0x002 ++#define FT_IC_INTR_RX_FULL 0x004 ++#define FT_IC_INTR_TX_OVER 0x008 ++#define FT_IC_INTR_TX_EMPTY 0x010 ++#define FT_IC_INTR_RD_REQ 0x020 ++#define FT_IC_INTR_TX_ABRT 0x040 ++#define FT_IC_INTR_RX_DONE 0x080 ++#define FT_IC_INTR_ACTIVITY 0x100 ++#define FT_IC_INTR_STOP_DET 0x200 ++#define FT_IC_INTR_START_DET 0x400 ++#define FT_IC_INTR_GEN_CALL 0x800 ++#define FT_IC_INTR_SMBCLK_EXT_LOW_TIMEOUT 0x1000 ++#define FT_IC_INTR_SMBCLK_TMO_LOW_TIMEOUT 0x2000 ++#define FT_IC_INTR_SMBSDA_LOW_TIMEOUT 0x4000 ++#define FT_IC_INTR_SMBALERT_IN_N 0x20000 ++ ++#define FT_IC_INTR_DEFAULT_MASK \ ++ (FT_IC_INTR_RX_FULL | FT_IC_INTR_TX_ABRT | FT_IC_INTR_STOP_DET) ++#define FT_IC_INTR_MASTER_MASK (FT_IC_INTR_DEFAULT_MASK | FT_IC_INTR_TX_EMPTY) ++#define FT_IC_INTR_SLAVE_MASK \ ++ (FT_IC_INTR_DEFAULT_MASK | FT_IC_INTR_RX_DONE | FT_IC_INTR_RX_UNDER | FT_IC_INTR_RD_REQ) ++#define FT_IC_INTR_SMBUS_MASK \ ++ (FT_IC_INTR_MASTER_MASK | FT_IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | \ ++ FT_IC_INTR_SMBCLK_TMO_LOW_TIMEOUT | FT_IC_INTR_SMBSDA_LOW_TIMEOUT) ++ ++#define FT_IC_INTR_SMBUS_TIME_MASK \ ++ (FT_IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | \ ++ FT_IC_INTR_SMBCLK_TMO_LOW_TIMEOUT | FT_IC_INTR_SMBSDA_LOW_TIMEOUT) ++ ++#define FT_IC_STATUS_ACTIVITY 0x1 ++#define FT_IC_STATUS_TFE BIT(2) ++#define FT_IC_STATUS_MASTER_ACTIVITY BIT(5) ++#define FT_IC_STATUS_SLAVE_ACTIVITY BIT(6) ++ ++#define FT_IC_SDA_HOLD_RX_SHIFT 16 ++#define FT_IC_SDA_HOLD_RX_MASK GENMASK(23, IC_SDA_HOLD_RX_SHIFT) ++ ++#define FT_IC_ERR_TX_ABRT 3 ++ ++#define FT_IC_TAR_10BITADDR_MASTER BIT(12) ++ ++#define FT_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3)) ++#define FT_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2) ++ ++#define FT_STATUS_IDLE 0x0 ++#define FT_STATUS_WRITE_IN_PROGRESS 0x1 ++#define FT_STATUS_READ_IN_PROGRESS 0x2 ++ ++/* ++ * operation modes ++ */ ++#define phyt_IC_MASTER 0 ++#define phyt_IC_SLAVE 1 ++ ++#define FT_ABRT_7B_ADDR_NOACK 0 ++#define FT_ABRT_10ADDR1_NOACK 1 ++#define FT_ABRT_10ADDR2_NOACK 2 ++#define FT_ABRT_TXDATA_NOACK 3 ++#define FT_ABRT_GCALL_NOACK 4 ++#define FT_ABRT_GCALL_READ 5 ++#define FT_ABRT_SBYTE_ACKDET 7 ++#define FT_ABRT_SBYTE_NORSTRT 9 ++#define FT_ABRT_10B_RD_NORSTRT 10 ++#define FT_ABRT_MASTER_DIS 11 ++#define FT_ARB_LOST 12 ++#define FT_ABRT_SLAVE_FLUSH_TXFIFO 13 ++#define FT_ABRT_SLAVE_ARBLOST 14 ++#define FT_ABRT_SLAVE_RD_INTX 15 ++ ++#define FT_IC_TX_ABRT_7B_ADDR_NOACK (1UL << FT_ABRT_7B_ADDR_NOACK) ++#define FT_IC_TX_ABRT_10ADDR1_NOACK (1UL << FT_ABRT_10ADDR1_NOACK) ++#define FT_IC_TX_ABRT_10ADDR2_NOACK (1UL << FT_ABRT_10ADDR2_NOACK) ++#define FT_IC_TX_ABRT_TXDATA_NOACK (1UL << FT_ABRT_TXDATA_NOACK) ++#define FT_IC_TX_ABRT_GCALL_NOACK (1UL << FT_ABRT_GCALL_NOACK) ++#define FT_IC_TX_ABRT_GCALL_READ (1UL << FT_ABRT_GCALL_READ) ++#define FT_IC_TX_ABRT_SBYTE_ACKDET (1UL << FT_ABRT_SBYTE_ACKDET) ++#define FT_IC_TX_ABRT_SBYTE_NORSTRT (1UL << FT_ABRT_SBYTE_NORSTRT) ++#define FT_IC_TX_ABRT_10B_RD_NORSTRT (1UL << FT_ABRT_10B_RD_NORSTRT) ++#define FT_IC_TX_ABRT_MASTER_DIS (1UL << FT_ABRT_MASTER_DIS) ++#define FT_IC_TX_ARB_LOST (1UL << FT_ARB_LOST) ++#define FT_IC_RX_ABRT_SLAVE_RD_INTX (1UL << FT_ABRT_SLAVE_RD_INTX) ++#define FT_IC_RX_ABRT_SLAVE_ARBLOST (1UL << FT_ABRT_SLAVE_ARBLOST) ++#define FT_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO (1UL << FT_ABRT_SLAVE_FLUSH_TXFIFO) ++ ++#define FT_IC_TX_ABRT_NOACK \ ++ (FT_IC_TX_ABRT_7B_ADDR_NOACK | FT_IC_TX_ABRT_10ADDR1_NOACK |\ ++ FT_IC_TX_ABRT_10ADDR2_NOACK | FT_IC_TX_ABRT_TXDATA_NOACK |\ ++ FT_IC_TX_ABRT_GCALL_NOACK) ++#define FT_CONTROLLER_TYPE_IIC 0 ++#define FT_CONTROLLER_TYPE_SMBUS 1 ++ ++#define FT_I2C_MSG_COMPLETE_OK 1 ++#define FT_I2C_MSG_COMPLETE_UNKNOWN 0 ++ ++#define FT_I2C_CON_MASTER_MODE_MASK 0x01 ++#define FT_I2C_CON_SLAVE_MODE_MASK (1 << 6) ++#define FT_I2C_CON_RESTART_MASK 0x20 ++ ++#define FT_I2C_CON_ADDR_MODE_MASK (1 << 3) ++#define FT_I2C_ADDR_7BIT_MODE (0) ++ ++#define FT_I2C_TRANS_TIMEOUT 0xF0 ++ ++#define FT_ACCESS_INTR_MASK 0x00000004 ++#define FT_DEFAULT_CLOCK_FREQUENCY 100000000 ++ ++#define FT_I2C_MSG_DATA_LEN 56 ++#define FT_I2C_SINGLE_BUF_LEN 51 ++#define FT_I2C_SINGLE_FRAME_CNT 32 ++ ++#define RV_ANSWER_DATA_SIZE 122 ++#define RV_ANSWER_DATA_CONTINUE 1 ++#define RV_ANSWER_DATA_END 0 ++ ++enum phyti2c_status_code { ++ FT_I2C_SUCCESS = 0, ++ FT_I2C_TIMEOUT, ++ FT_I2C_CNT_ERR, ++ FT_I2C_TX_ABRT, ++ FT_I2C_INT_ERR, ++ FT_I2C_BLOCK_SIZE, ++ FT_I2C_INVALID_ADDR, ++ FT_I2C_TRANS_PACKET_FAIL, ++ /*The RV result must put above*/ ++ FT_I2C_RUNNING, ++ FT_I2C_CHECK_STATUS_ERR ++}; ++ ++struct i2c_ft_rv_event_mng { ++ u8 event_cnt; ++}; ++ ++enum phyti2c_msg_cmd_id { ++ PHYTI2C_MSG_CMD_DEFAULT = 0, ++ PHYTI2C_MSG_CMD_SET, ++ PHYTI2C_MSG_CMD_GET, ++ PHYTI2C_MSG_CMD_DATA, ++ PHYTI2C_MSG_CMD_REPORT, ++ PHYTI2C_SYS_PROTOCOL, ++}; ++ ++enum phyti2c_msg_default_subid { ++ PHYTI2C_MSG_CMD_DEFAULT_RESV = 0, ++ PHYTI2C_MSG_CMD_DEFAULT_RESUME, ++ PHYTI2C_MSG_CMD_DEFAULT_SLV ++}; ++ ++struct i2c_ft_default_cfg_msg { ++ u32 ss_hcnt; ++ u32 ss_lcnt; ++ u32 fs_hcnt; ++ u32 fs_lcnt; ++ u32 hs_hcnt; ++ u32 hs_lcnt; ++ u32 sda_hold; ++ u32 tx_fifo_thr; ++ u32 rx_fifo_thr; ++ u32 smbclk_mext; ++ u32 smbclk_timeout; ++ u32 smbdat_timeout; ++ u32 cfg; ++ u32 intr_mask; ++}; ++ ++enum phyti2c_set_subid { ++ PHYTI2C_MSG_CMD_SET_MODULE_EN = 0, ++ PHYTI2C_MSG_CMD_SET_MODE, ++ PHYTI2C_MSG_CMD_SET_RESTART, ++ PHYTI2C_MSG_CMD_SET_ADDR_MODE, ++ PHYTI2C_MSG_CMD_SET_SPEED, ++ PHYTI2C_MSG_CMD_SET_INT_TL, ++ PHYTI2C_MSG_CMD_SET_SDA_HOLD, ++ PHYTI2C_MSG_CMD_SET_INTERRUPT, ++ PHYTI2C_MSG_CMD_SET_RX_FIFO_FULL, ++ PHYTI2C_MSG_CMD_SET_STOP_DET_IF_ADDRESSED, ++ PHYTI2C_MSG_CMD_SET_WRITE_PROTECT, ++ PHYTI2C_MSG_CMD_SET_SMBCLK_LOW_MEXT, ++ PHYTI2C_MSG_CMD_SET_SMBCLK_LOW_TIMEOUT, ++ PHYTI2C_MSG_CMD_SET_SMBDAT_STUCK_TIMEOUT, ++ PHYTI2C_MSG_CMD_SET_ADDR, ++ PHYTI2C_MSG_CMD_SET_SUSPEND ++}; ++ ++enum phyti2c_data_subid { ++ PHYTI2C_MSG_CMD_DATA_XFER = 0, ++ PHYTI2C_MSG_CMD_DATA_SLAVE ++}; ++ ++enum phyti2c_report_subid { ++ PHYTI2C_MSG_CMD_SMBCLK_EXT_LOW_TIMEOUT = 0, ++ PHYTI2C_MSG_CMD_SMBCLK_TMO_LOW_TIMEOUT, ++ PHYTI2C_MSG_CMD_SMBSDA_LOW_TIMEOUT, ++ PHYTI2C_MSG_CMD_SMBALERT_IN_N, ++ PHYTI2C_MSG_CMD_SLAVE_EVENT, ++}; ++ ++struct i2c_phyt_transfer { ++ u32 tx_cmd_cnt; ++ u32 cur_cmd_cnt; ++ u32 cur_index; ++ u32 opt_finish_len; ++ u32 tx_ring_cnt; ++ bool is_need_check; ++ bool is_last_frame; ++}; ++ ++struct i2c_phyt_dev { ++ struct device *dev; ++ void __iomem *base; ++ void __iomem *log_addr; ++ void *tx_shmem_addr; ++ void *rx_shmem_addr; ++ u8 *tx_buf; ++ u8 *rx_buf; ++ struct clk *clk; ++ struct reset_control *rst; ++ struct i2c_client *slave; ++ struct i2c_client *ara; ++ struct i2c_msg *msgs; ++ struct timer_list timer; ++ struct phytium_pci_i2c *controller; ++ ++ int module; ++ int irq; ++ u32 intr_mask; ++ u32 flags; ++ u32 total_shmem_len; ++ u32 total_cnt; ++ int mode; ++ struct i2c_phyt_transfer mng; ++ struct completion cmd_complete; ++ struct i2c_adapter adapter; ++ struct i2c_smbus_alert_setup alert_data; ++ ++ bool complete_flag; ++ u32 abort_source; ++ ++ int msgs_num; ++ int msg_err; ++ u32 tx_buf_len; ++ u32 rx_buf_len; ++ ++ u32 master_cfg; ++ u32 slave_cfg; ++ u32 functionality; ++ ++ u8 real_index[FT_I2C_SINGLE_FRAME_CNT]; ++ struct i2c_timings timings; ++ u32 sda_hold_time; ++ u16 ss_hcnt; ++ u16 ss_lcnt; ++ u16 fs_hcnt; ++ u16 fs_lcnt; ++ u16 fp_hcnt; ++ u16 fp_lcnt; ++ u16 hs_hcnt; ++ u16 hs_lcnt; ++ ++ bool alive_enabled; ++ bool debug_enabled; ++ u32 log_size; ++ bool pm_disabled; ++ spinlock_t shmem_spin; ++ ++ u32 (*get_clk_rate_khz)(struct i2c_phyt_dev *dev); ++ void (*disable)(struct i2c_phyt_dev *dev); ++ void (*disable_int)(struct i2c_phyt_dev *dev); ++ void (*watchdog)(struct i2c_phyt_dev *dev); ++ int (*init)(struct i2c_phyt_dev *dev); ++}; ++ ++struct phyt_msg_head { ++ u8 resv; ++ u8 seq; ++ u8 cmd_type; ++ u8 cmd_subid; ++ u16 len; ++ u8 status1; ++ u8 status0; ++}; ++ ++struct phyt_msg_info { ++ struct phyt_msg_head head; ++ u8 data[FT_I2C_MSG_DATA_LEN]; ++}; ++ ++struct i2c_ft_trans_msg_info { ++ u16 addr; ++ u16 flags; ++ u8 type; ++} __packed; ++ ++struct i2c_phyt_bus_speed_info { ++ u8 speed_mode; ++ u8 calc_en; ++ u16 scl_hcnt; ++ u16 scl_lcnt; ++ u32 sda_hold; ++}; ++ ++struct i2c_phyt_fifo_threshold { ++ u8 rx_fifo_threshold; ++ u8 tx_fifo_threshold; ++}; ++ ++struct i2c_phyt_sda_hold_info { ++ u32 sda_hold; ++}; ++ ++static inline void i2c_phyt_write_reg(struct i2c_phyt_dev *dev, ++ u32 reg_offset, u32 reg_value) ++{ ++ writel_relaxed(reg_value, dev->base + reg_offset); ++} ++ ++static inline u32 i2c_phyt_read_reg(struct i2c_phyt_dev *dev, u32 reg_offset) ++{ ++ return readl_relaxed(dev->base + reg_offset); ++} ++ ++unsigned long i2c_phyt_clk_rate(struct i2c_phyt_dev *dev); ++int i2c_phyt_prepare_clk(struct i2c_phyt_dev *dev, bool prepare); ++u32 i2c_phyt_func(struct i2c_adapter *adap); ++u32 i2c_phyt_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset); ++u32 i2c_phyt_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); ++void i2c_phyt_default_cfg(struct i2c_phyt_dev *dev, ++ struct i2c_ft_default_cfg_msg *buf); ++void i2c_phyt_set_suspend(struct i2c_phyt_dev *dev); ++void i2c_phyt_enable_debug(struct i2c_phyt_dev *dev); ++void i2c_phyt_disable_debug(struct i2c_phyt_dev *dev); ++void i2c_phyt_show_log(struct i2c_phyt_dev *dev); ++void i2c_phyt_enable_alive(struct i2c_phyt_dev *dev); ++void i2c_phyt_disable_alive(struct i2c_phyt_dev *dev); ++void i2c_phyt_common_watchdog(struct i2c_phyt_dev *dev); ++int i2c_phyt_malloc_log_mem(struct i2c_phyt_dev *dev); ++int i2c_phyt_rv_data_cmd_handle(struct phyt_msg_info *rx_msg); ++int i2c_phyt_master_probe(struct i2c_phyt_dev *dev); ++void i2c_phyt_handle_tx_abort(struct i2c_phyt_dev *dev); ++int i2c_phyt_check_result(struct i2c_phyt_dev *dev); ++void i2c_phyt_set_cmd8(struct i2c_phyt_dev *dev, u8 sub_cmd, u8 data); ++void i2c_phyt_set_cmd16(struct i2c_phyt_dev *dev, u8 sub_cmd, u16 data); ++void i2c_phyt_set_cmd32(struct i2c_phyt_dev *dev, u8 sub_cmd, u32 data); ++void i2c_phyt_common_set_cmd(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *i2c_mng_msg, u8 cmd, u8 sub_cmd); ++void i2c_phyt_disable_int(struct i2c_phyt_dev *dev); ++void i2c_phyt_set_int_tl(struct i2c_phyt_dev *dev, u8 tx_threshold, ++ u8 rx_threshold); ++int i2c_phyt_slave_probe(struct i2c_phyt_dev *dev); ++void i2c_phyt_set_module_en(struct i2c_phyt_dev *dev, u8 data); ++void i2c_phyt_set_sda_hold(struct i2c_phyt_dev *dev, u32 data); ++void i2c_phyt_disable(struct i2c_phyt_dev *dev); ++int i2c_phyt_slave_event_process(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *rx_msg, u32 head, u32 tail); ++void i2c_phyt_data_cmd8_array(struct i2c_phyt_dev *dev, u8 sub_cmd, u8 *data, ++ int len); ++void i2c_phyt_slave_isr_handle(struct i2c_phyt_dev *dev); ++void i2c_phyt_master_isr_handle(struct i2c_phyt_dev *dev); ++int i2c_phyt_master_smbus_alert_process(struct i2c_phyt_dev *dev); ++void i2c_phyt_common_regfile_enable_int(struct i2c_phyt_dev *dev); ++void i2c_phyt_common_regfile_disable_int(struct i2c_phyt_dev *dev); ++void i2c_phyt_common_regfile_clear_rv2ap_int(struct i2c_phyt_dev *dev, u32 stat); ++void i2c_phyt_notify_rv(struct i2c_phyt_dev *dev, bool need_check); ++int i2c_phyt_check_status(struct i2c_phyt_dev *dev, struct phyt_msg_info *msg); ++void i2c_phyt_set_int_interrupt(struct i2c_phyt_dev *dev, ++ u32 is_enable, u32 intr_mask); ++#endif +diff --git a/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-master.c b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-master.c +new file mode 100644 +index 000000000000..24c8c7bcac3b +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-master.c +@@ -0,0 +1,591 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Phytium I2C adapter driver. ++ * ++ * Copyright (C) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "i2c-phyt-core.h" ++ ++#define FT_DEFAULT_TIMEOUT (FT_DEFAULT_CLOCK_FREQUENCY / 1000 * 35) ++ ++#define FT_I2C_MSG_MNG_SIZE 8 ++#define FT_I2C_SHMEM_STORE_OFFSET (FT_I2C_MSG_MNG_SIZE + sizeof(struct i2c_ft_trans_msg_info)) ++ ++static int i2c_phyt_master_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg msgs[], int num); ++static void i2c_phyt_master_parse_data(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *shmem_msg, ++ int index); ++static int i2c_phyt_master_default_init(struct i2c_phyt_dev *dev); ++static int i2c_phyt_master_set_timings_master(struct i2c_phyt_dev *dev); ++ ++static const struct i2c_algorithm i2c_phyt_master_algo = { ++ .master_xfer = i2c_phyt_master_xfer, ++ .functionality = i2c_phyt_func, ++}; ++ ++ ++static int i2c_phyt_master_set_timings_master(struct i2c_phyt_dev *dev) ++{ ++ const char *mode_str, *fp_str = ""; ++ u32 sda_falling_time, scl_falling_time; ++ struct i2c_timings *t = &dev->timings; ++ u32 ic_clk; ++ int ret = 0; ++ ++ /* Set standard and fast speed dividers for high/low periods */ ++ sda_falling_time = t->sda_fall_ns ?: 300; /* ns */ ++ scl_falling_time = t->scl_fall_ns ?: 300; /* ns */ ++ ++ /* Calculate SCL timing parameters for standard mode if not set */ ++ if (!dev->ss_hcnt || !dev->ss_lcnt) { ++ ic_clk = i2c_phyt_clk_rate(dev); ++ dev->ss_hcnt = ++ i2c_phyt_scl_hcnt(ic_clk, 4000,/* tHD;STA = tHIGH = 4.0 us */ ++ sda_falling_time, 0,/* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ ++ dev->ss_lcnt = i2c_phyt_scl_lcnt(ic_clk, 4700, /* tLOW = 4.7 us */ ++ scl_falling_time, 0); /* No offset */ ++ } ++ dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", dev->ss_hcnt, dev->ss_lcnt); ++ /* ++ * Set SCL timing parameters for fast mode or fast mode plus. Only ++ * difference is the timing parameter values since the registers are ++ * the same. ++ */ ++ if (t->bus_freq_hz == 1000000) { ++ /* ++ * Check are fast mode plus parameters available and use ++ * fast mode if not. ++ */ ++ if (dev->fp_hcnt && dev->fp_lcnt) { ++ dev->fs_hcnt = dev->fp_hcnt; ++ dev->fs_lcnt = dev->fp_lcnt; ++ fp_str = " Plus"; ++ } ++ } ++ /* ++ * Calculate SCL timing parameters for fast mode if not set. They are ++ * needed also in high speed mode. ++ */ ++ if (!dev->fs_hcnt || !dev->fs_lcnt) { ++ ic_clk = i2c_phyt_clk_rate(dev); ++ dev->fs_hcnt = ++ i2c_phyt_scl_hcnt(ic_clk, 600, /* tHD;STA = tHIGH = 0.6 us */ ++ sda_falling_time, 0, /* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ ++ dev->fs_lcnt = i2c_phyt_scl_lcnt(ic_clk, 1300, /* tLOW = 1.3 us */ ++ scl_falling_time, 0); /* No offset */ ++ } ++ dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", fp_str, dev->fs_hcnt, dev->fs_lcnt); ++ ++ if (dev->hs_hcnt && dev->hs_lcnt) ++ dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", dev->hs_hcnt, ++ dev->hs_lcnt); ++ ++ switch (dev->master_cfg & FT_IC_CON_SPEED_MASK) { ++ case FT_IC_CON_SPEED_STD: ++ mode_str = "Standard Mode"; ++ break; ++ case FT_IC_CON_SPEED_HIGH: ++ mode_str = "High Speed Mode"; ++ break; ++ default: ++ mode_str = "Fast Mode"; ++ } ++ dev_dbg(dev->dev, "Bus speed: %s%s\n", mode_str, fp_str); ++ ++ return ret; ++} ++ ++int i2c_phyt_master_smbus_alert_process(struct i2c_phyt_dev *dev) ++{ ++ if (dev->ara) ++ i2c_handle_smbus_alert(dev->ara); ++ else ++ dev_dbg(dev->dev, "alert do nothing\n"); ++ ++ return 0; ++} ++ ++static int i2c_phyt_master_update_new_msg(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info shmem_msg; ++ struct phyt_msg_info *tx_shmem = (struct phyt_msg_info *)dev->tx_shmem_addr; ++ struct i2c_ft_trans_msg_info *i2c_msg_info; ++ struct i2c_msg *msgs = dev->msgs; ++ int remain_len; ++ ++ /*Check the current index and the len are valid */ ++ if ((dev->mng.cur_index >= dev->msgs_num) || ++ (msgs[dev->mng.cur_index].len < dev->mng.opt_finish_len)) ++ return -EINVAL; ++ ++ memset(&shmem_msg, 0, sizeof(struct phyt_msg_info)); ++ i2c_msg_info = (struct i2c_ft_trans_msg_info *)&shmem_msg.data[0]; ++ /*Get the remain len*/ ++ remain_len = msgs[dev->mng.cur_index].len - dev->mng.opt_finish_len; ++ if (!remain_len) { ++ /*Use the next index*/ ++ if (dev->mng.cur_index + 1 >= dev->msgs_num) ++ return FT_I2C_RUNNING; ++ ++ dev->mng.cur_index++; ++ ++ if ((msgs[dev->mng.cur_index - 1].flags & I2C_M_RD) != ++ (msgs[dev->mng.cur_index].flags & I2C_M_RD)) ++ i2c_msg_info->type = FT_I2C_TRANS_FRAME_RESTART; ++ ++ dev->mng.opt_finish_len = 0; ++ remain_len = msgs[dev->mng.cur_index].len; ++ } ++ ++ /*Set the Head.len and Head.seq*/ ++ shmem_msg.head.len = remain_len; ++ if (remain_len > FT_I2C_SINGLE_BUF_LEN) { ++ shmem_msg.head.len = FT_I2C_SINGLE_BUF_LEN; ++ } else { ++ if (dev->mng.cur_index + 1 >= dev->msgs_num) { ++ i2c_msg_info->type |= FT_I2C_TRANS_FRAME_END; ++ dev->mng.is_last_frame = true; ++ } ++ } ++ /*Set other info of the Head*/ ++ shmem_msg.head.seq = dev->total_cnt--; ++ shmem_msg.head.cmd_type = PHYTI2C_MSG_CMD_DATA; ++ shmem_msg.head.cmd_subid = PHYTI2C_MSG_CMD_DATA_XFER; ++ shmem_msg.head.status0 = FT_I2C_MSG_COMPLETE_UNKNOWN; ++ ++ /*store addr flags of struct i2c_msg*/ ++ i2c_msg_info->addr = msgs[dev->mng.cur_index].addr; ++ i2c_msg_info->flags = msgs[dev->mng.cur_index].flags; ++ ++ dev->total_shmem_len = FT_I2C_SHMEM_STORE_OFFSET; ++ /*store data*/ ++ if (!(msgs[dev->mng.cur_index].flags & I2C_M_RD)) { ++ memcpy(&shmem_msg.data[sizeof(struct i2c_ft_trans_msg_info)], ++ &msgs[dev->mng.cur_index].buf[dev->mng.opt_finish_len], ++ shmem_msg.head.len); ++ dev->total_shmem_len += shmem_msg.head.len; ++ } ++ ++ dev->mng.opt_finish_len += shmem_msg.head.len; ++ /*update new data to shmem*/ ++ memcpy(&tx_shmem[dev->mng.tx_cmd_cnt % dev->mng.tx_ring_cnt], ++ &shmem_msg, dev->total_shmem_len); ++ ++ dev->real_index[dev->mng.tx_cmd_cnt % dev->mng.tx_ring_cnt] = ++ dev->mng.cur_index; ++ /*Update the Tx_Tail*/ ++ dev->mng.tx_cmd_cnt++; ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_TAIL, ++ dev->mng.tx_cmd_cnt % dev->mng.tx_ring_cnt); ++ return FT_I2C_RUNNING; ++} ++ ++static int i2c_phyt_master_handle(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info *tx_shmem = (struct phyt_msg_info *)dev->tx_shmem_addr; ++ struct phyt_msg_info shmem_msg; ++ u32 tx_head; ++ int ret; ++ ++ if (dev->mng.cur_cmd_cnt >= dev->mng.tx_cmd_cnt) ++ return 0; ++ ++ /*Get the index of general msg*/ ++ tx_head = dev->mng.cur_cmd_cnt % dev->mng.tx_ring_cnt; ++ dev->mng.cur_cmd_cnt++; ++ ++ /*Read the general_msg*/ ++ memcpy(&shmem_msg, &tx_shmem[tx_head], sizeof(struct phyt_msg_info)); ++ ret = i2c_phyt_check_status(dev, &shmem_msg); ++ ++ /*Error*/ ++ if (ret) ++ return -EINVAL; ++ ++ /*no check cmd*/ ++ if (!dev->mng.is_need_check) ++ return 0; ++ ++ i2c_phyt_master_parse_data(dev, &shmem_msg, tx_head); ++ /*No need to update new data*/ ++ if (dev->mng.is_last_frame) { ++ if (dev->mng.cur_cmd_cnt == dev->mng.tx_cmd_cnt) ++ return 0;/*This is last frame */ ++ return FT_I2C_RUNNING;/*There are some msgs needed to process*/ ++ } ++ return i2c_phyt_master_update_new_msg(dev); ++} ++ ++static int i2c_phyt_master_calc_total_frame_cnt(struct i2c_phyt_dev *dev) ++{ ++ int i, frame_cnt = 0, len = 0, remain_len; ++ struct i2c_msg *msgs = dev->msgs; ++ ++ for (i = 0; i < dev->msgs_num; i++) { ++ len = 0; ++ remain_len = msgs[i].len; ++ while (len < remain_len) { ++ if (remain_len > FT_I2C_SINGLE_BUF_LEN) ++ len += FT_I2C_SINGLE_BUF_LEN; ++ else ++ len = remain_len; ++ ++ frame_cnt++; ++ } ++ } ++ return frame_cnt; ++} ++ ++static void i2c_phyt_master_xfer_single_frame(struct i2c_phyt_dev *dev) ++{ ++ struct phyt_msg_info i2c_mng_msg; ++ struct i2c_ft_trans_msg_info *i2c_msg_info; ++ struct phyt_msg_info *shmem_msg = ++ (struct phyt_msg_info *)dev->tx_shmem_addr; ++ struct i2c_msg *msgs = dev->msgs; ++ int i, len = 0, remain_len; ++ ++ dev->total_cnt = i2c_phyt_master_calc_total_frame_cnt(dev); ++ if (dev->total_cnt) ++ dev->total_cnt--; ++ ++ /*orign info*/ ++ for (i = 0; i < dev->msgs_num; i++) { ++ remain_len = msgs[i].len; ++ dev->mng.opt_finish_len = 0; ++ ++ while (dev->mng.tx_cmd_cnt < dev->mng.tx_ring_cnt - 1) { ++ dev->total_shmem_len = 0; ++ memset(&i2c_mng_msg, 0, sizeof(i2c_mng_msg)); ++ ++ i2c_mng_msg.head.seq = dev->total_cnt--; ++ /*Set the Head.len*/ ++ len = remain_len; ++ if (remain_len >= FT_I2C_SINGLE_BUF_LEN) ++ len = FT_I2C_SINGLE_BUF_LEN; ++ i2c_mng_msg.head.len = len; ++ ++ /*Set other info of the Head*/ ++ i2c_mng_msg.head.cmd_type = PHYTI2C_MSG_CMD_DATA; ++ i2c_mng_msg.head.cmd_subid = PHYTI2C_MSG_CMD_DATA_XFER; ++ i2c_mng_msg.head.status0 = FT_I2C_MSG_COMPLETE_UNKNOWN; ++ ++ /*Store addr flags of struct i2c_msg*/ ++ i2c_msg_info = ++ (struct i2c_ft_trans_msg_info *)&i2c_mng_msg.data[0]; ++ i2c_msg_info->addr = (u16)msgs[i].addr; ++ i2c_msg_info->flags = (u16)msgs[i].flags; ++ ++ /*Set the Head.seq (Start)*/ ++ if (!dev->mng.tx_cmd_cnt) ++ i2c_msg_info->type = FT_I2C_TRANS_FRAME_START; ++ ++ /*Set the Head.seq (Restart)*/ ++ if ((i) && ((msgs[i - 1].flags & I2C_M_RD) != ++ (msgs[i].flags & I2C_M_RD))) { ++ if (remain_len == msgs[i].len) ++ i2c_msg_info->type = FT_I2C_TRANS_FRAME_RESTART; ++ } ++ /*Set the Head.seq (End)*/ ++ if (((i + 1) >= dev->msgs_num) && (len == remain_len)) { ++ dev->mng.is_last_frame = true; ++ i2c_msg_info->type |= FT_I2C_TRANS_FRAME_END; ++ } ++ ++ ++ dev->total_shmem_len = FT_I2C_SHMEM_STORE_OFFSET; ++ /*store data*/ ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ memcpy(&i2c_mng_msg.data[sizeof( ++ struct i2c_ft_trans_msg_info)], ++ &msgs[i].buf[dev->mng.opt_finish_len], len); ++ dev->total_shmem_len += len; ++ } ++ /*Update to share memory*/ ++ memcpy(&shmem_msg[dev->mng.tx_cmd_cnt], &i2c_mng_msg, ++ dev->total_shmem_len); ++ ++ /*Store the index of the i2c_msgs\the current index and the finished len*/ ++ dev->real_index[dev->mng.tx_cmd_cnt] = i; ++ dev->mng.cur_index = i; ++ dev->mng.opt_finish_len += len; ++ /*Record the count of AP2RV's msg*/ ++ dev->mng.tx_cmd_cnt++; ++ ++ remain_len -= len; ++ if (!remain_len) ++ break; ++ } ++ } ++ /*Update the Tx_Tail*/ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_TAIL, dev->mng.tx_cmd_cnt); ++ i2c_phyt_notify_rv(dev, true); ++} ++ ++static int i2c_phyt_master_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg msgs[], int num) ++{ ++ struct i2c_phyt_dev *dev = i2c_get_adapdata(adapter); ++ int ret; ++ ++ pm_runtime_get_sync(dev->dev); ++ ++ dev->msgs = msgs; ++ dev->msgs_num = num; ++ dev->msg_err = 0; ++ dev->abort_source = 0; ++ dev->rx_buf_len = 0; ++ dev->mng.tx_cmd_cnt = 0; ++ dev->mng.cur_cmd_cnt = 0; ++ dev->mng.is_last_frame = false; ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_HEAD, 0); ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_TAIL, 0); ++ ++ i2c_phyt_master_xfer_single_frame(dev); ++ ++ ret = i2c_phyt_check_result(dev); ++ if (!ret) { ++ ret = num; ++ } else { ++ if (dev->abort_source != FT_I2C_SUCCESS) { ++ i2c_phyt_handle_tx_abort(dev); ++ if ((dev->abort_source & BIT(FT_I2C_TIMEOUT)) || ++ (dev->abort_source & BIT(FT_I2C_TRANS_PACKET_FAIL))) { ++ i2c_phyt_set_module_en( ++ dev, FT_I2C_ADAPTER_MODULE_RESET); ++ i2c_phyt_check_result(dev); ++ i2c_phyt_master_default_init(dev); ++ ret = -ETIMEDOUT; ++ goto done; ++ } ++ ret = -EINVAL; ++ } ++ } ++ ++done: ++ pm_runtime_mark_last_busy(dev->dev); ++ pm_runtime_put_autosuspend(dev->dev); ++ ++ return ret; ++} ++ ++static void ++i2c_phyt_master_parse_data(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *shmem_msg, ++ int index) ++{ ++ int real_index; ++ struct i2c_ft_trans_msg_info *i2c_msg_info; ++ struct i2c_msg *msgs = dev->msgs; ++ ++ i2c_msg_info = (struct i2c_ft_trans_msg_info *)&shmem_msg->data[0]; ++ /*Find the real index of i2c_msgs*/ ++ real_index = dev->real_index[index]; ++ if (real_index >= dev->msgs_num) ++ return; ++ ++ if (i2c_msg_info->flags & I2C_M_RD) { ++ memcpy(&msgs[real_index].buf[dev->rx_buf_len], ++ &shmem_msg->data[sizeof(struct i2c_ft_trans_msg_info)], ++ shmem_msg->head.len); ++ dev->rx_buf_len += shmem_msg->head.len; ++ } ++} ++ ++static int i2c_phyt_master_default_init(struct i2c_phyt_dev *dev) ++{ ++ int ret; ++ struct i2c_ft_default_cfg_msg cfg_info; ++ ++ cfg_info.ss_hcnt = dev->ss_hcnt; ++ cfg_info.ss_lcnt = dev->ss_lcnt; ++ cfg_info.fs_hcnt = dev->fs_hcnt; ++ cfg_info.fs_lcnt = dev->fs_lcnt; ++ cfg_info.hs_hcnt = dev->hs_hcnt; ++ cfg_info.hs_lcnt = dev->hs_lcnt; ++ cfg_info.sda_hold = dev->sda_hold_time; ++ cfg_info.tx_fifo_thr = 3; ++ cfg_info.rx_fifo_thr = 0; ++ cfg_info.smbclk_mext = FT_DEFAULT_TIMEOUT; ++ cfg_info.smbclk_timeout = FT_DEFAULT_TIMEOUT; ++ cfg_info.smbdat_timeout = FT_DEFAULT_TIMEOUT; ++ cfg_info.cfg = dev->master_cfg; ++ cfg_info.intr_mask = dev->intr_mask; ++ i2c_phyt_default_cfg(dev, &cfg_info); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set module open: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t i2c_phyt_master_regfile_isr(int this_irq, void *dev_id) ++{ ++ struct i2c_phyt_dev *dev = (struct i2c_phyt_dev *)dev_id; ++ struct phyt_msg_info *rx_msg = (struct phyt_msg_info *)dev->rx_shmem_addr; ++ u32 stat, head, tail; ++ int ret; ++ ++ stat = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_STAT); ++ ++ if (!(stat & FT_I2C_RV2AP_INTR_BIT4)) { ++ dev_warn(dev->dev, "unexpect i2c_phyt regfile intr, stat:%#x\n", stat); ++ return IRQ_NONE; ++ } ++ ++ i2c_phyt_common_regfile_clear_rv2ap_int(dev, stat); ++ ++ if (!dev->mng.tx_ring_cnt) { ++ dev_err(dev->dev, "tx_ring_cnt is zero\n"); ++ return IRQ_NONE; ++ } ++ head = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_TX_HEAD) % dev->mng.tx_ring_cnt; ++ tail = dev->mng.cur_cmd_cnt % dev->mng.tx_ring_cnt; ++ do { ++ tail++; ++ tail %= dev->mng.tx_ring_cnt; ++ if (dev->complete_flag) { ++ if (rx_msg->head.cmd_type == PHYTI2C_MSG_CMD_REPORT) ++ goto done; ++ ++ ret = i2c_phyt_master_handle(dev); ++ if (ret == FT_I2C_RUNNING) ++ continue; ++ ++ dev->complete_flag = false; ++ dev->mng.cur_cmd_cnt = 0; ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_HEAD, 0); ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_TX_TAIL, 0); ++ complete(&dev->cmd_complete); ++ return IRQ_HANDLED; ++ } ++ } while (tail != head); ++done: ++ i2c_phyt_master_isr_handle(dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int i2c_phyt_enable_smbus_alert(struct i2c_phyt_dev *i2c_dev) ++{ ++ struct i2c_adapter *adap = &i2c_dev->adapter; ++ struct i2c_smbus_alert_setup setup; ++ ++ setup.irq = 0; ++ i2c_dev->ara = i2c_new_smbus_alert_device(adap, &setup); ++ ++ if (IS_ERR(i2c_dev->ara)) ++ return PTR_ERR(i2c_dev->ara); ++ ++ return 0; ++} ++ ++int i2c_phyt_master_probe(struct i2c_phyt_dev *dev) ++{ ++ struct i2c_adapter *adapter = &dev->adapter; ++ unsigned long irq_flags; ++ int ret; ++ u32 alert = 0; ++ ++ init_completion(&dev->cmd_complete); ++ ++ i2c_phyt_common_regfile_disable_int(dev); ++ i2c_phyt_common_regfile_clear_rv2ap_int(dev, 0); ++ ++ irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND; ++ ret = devm_request_irq(dev->dev, dev->irq, i2c_phyt_master_regfile_isr, irq_flags, ++ dev_name(dev->dev), dev); ++ if (ret) { ++ dev_err(dev->dev, "failure requesting irq %i: %d\n", ++ dev->irq, ret); ++ return ret; ++ } ++ ++ i2c_phyt_common_regfile_enable_int(dev); ++ ++ ret = i2c_phyt_master_set_timings_master(dev); ++ if (ret) { ++ dev_err(dev->dev, "master set times\n"); ++ return ret; ++ } ++ ++ dev->intr_mask = FT_IC_INTR_SMBUS_TIME_MASK; ++ ret = i2c_phyt_master_default_init(dev); ++ if (ret) { ++ dev_err(dev->dev, "master default init\n"); ++ return ret; ++ } ++ dev->init = i2c_phyt_master_default_init; ++ dev->disable = i2c_phyt_set_suspend; ++ dev->disable_int = i2c_phyt_disable_int; ++ ++ /* XXX: should be initialized in firmware, remove it in future */ ++ snprintf(adapter->name, sizeof(adapter->name), "Phytium I2C_2.0 Master adapter"); ++ adapter->retries = 3; ++ adapter->algo = &i2c_phyt_master_algo; ++ adapter->dev.parent = dev->dev; ++ i2c_set_adapdata(adapter, dev); ++ /* ++ * Increment PM usage count during adapter registration in order to ++ * avoid possible spurious runtime suspend when adapter device is ++ * registered to the device core and immediate resume in case bus has ++ * registered I2C slaves that do I2C transfers in their probe. ++ */ ++ pm_runtime_get_noresume(dev->dev); ++ ++ ret = i2c_add_numbered_adapter(adapter); ++ if (ret) { ++ dev_err(dev->dev, "fail to add adapter: %d\n", ret); ++ goto exit_probe; ++ } ++ ++ if (of_property_read_bool(dev->dev->of_node, "smbus-alert")) ++ alert = 1; ++ else if (has_acpi_companion(dev->dev)) ++ fwnode_property_read_u32_array(dev->dev->fwnode, "smbus_alert", &alert, 1); ++ ++ if (alert) { ++ ret = i2c_phyt_enable_smbus_alert(dev); ++ if (ret) { ++ dev_err(dev->dev, ++ "failed to enable SMBus alert protocol (%d)\n", ret); ++ } ++ dev->intr_mask |= FT_IC_INTR_SMBALERT_IN_N; ++ i2c_phyt_set_int_interrupt(dev, FT_I2C_ENABLE_INTERRUPT, dev->intr_mask); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) ++ dev_warn(dev->dev, "fail to set interrupt: %d\n", ret); ++ } else ++ dev_info(dev->dev, "find no alert\n"); ++ ++exit_probe: ++ pm_runtime_put_noidle(dev->dev); ++ dev_info(dev->dev, "i2c_2.0 master probe ok\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(i2c_phyt_master_probe); ++ ++MODULE_DESCRIPTION("Phytium I2C bus master adapter"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-platform.c b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-platform.c +new file mode 100644 +index 000000000000..45ad303f2875 +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-platform.c +@@ -0,0 +1,525 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Phytium I2C adapter driver. ++ * ++ * Copyright (C) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "i2c-phyt-core.h" ++ ++#define DRV_NAME "i2c-phytium-v2-platform" ++ ++static u32 i2c_phyt_get_clk_rate_khz(struct i2c_phyt_dev *dev) ++{ ++ return clk_get_rate(dev->clk)/1000; ++} ++ ++static ssize_t debug_show(struct device *dev, ++ struct device_attribute *da, ++ char *buf) ++{ ++ struct i2c_phyt_dev *adapter_dev = dev_get_drvdata(dev); ++ ssize_t ret; ++ u32 reg; ++ ++ reg = i2c_phyt_read_reg(adapter_dev, FT_I2C_REGFILE_DEBUG); ++ ret = sprintf(buf, "%x\n", reg); ++ ++ return ret; ++} ++ ++static ssize_t debug_store(struct device *dev, ++ struct device_attribute *da, ++ const char *buf, size_t size) ++{ ++ u8 loc, dis_en, status = 0; ++ char *p; ++ char *token; ++ long value; ++ u32 reg; ++ struct i2c_phyt_dev *adapter_dev = dev_get_drvdata(dev); ++ ++ dev_info(dev, "echo alive(1)/debug(0) enable(1)/disable(0) > debug\n"); ++ dev_info(dev, "Example:echo 0 1 > debug; Enable Debug Function\n"); ++ ++ p = kmalloc(size, GFP_KERNEL); ++ strscpy(p, buf, size); ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ ++ status = kstrtol(token, 0, &value); ++ if (status) ++ return status; ++ loc = (u8)value; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ ++ status = kstrtol(token, 0, &value); ++ if (status) ++ return status; ++ dis_en = value; ++ ++ reg = i2c_phyt_read_reg(adapter_dev, FT_I2C_REGFILE_DEBUG); ++ ++ if (loc == 1) { ++ if (dis_en == 1) { ++ adapter_dev->alive_enabled = true; ++ reg |= BIT(loc); ++ } else if (dis_en == 0) { ++ adapter_dev->alive_enabled = false; ++ reg &= ~BIT(loc); ++ } ++ } else if (loc == 0) { ++ if (dis_en == 1) { ++ adapter_dev->debug_enabled = true; ++ reg |= BIT(loc); ++ } else if (dis_en == 0) { ++ adapter_dev->debug_enabled = false; ++ reg &= ~BIT(loc); ++ } ++ } ++ ++ i2c_phyt_write_reg(adapter_dev, FT_I2C_REGFILE_DEBUG, reg); ++ ++ dev_info(dev, "reg write reg =0x%x, loc = %d, val=%d\n", reg, loc, dis_en); ++ ++ kfree(p); ++ return size; ++} ++static DEVICE_ATTR_RW(debug); ++ ++static struct attribute *i2c_ft_device_attrs[] = { ++ &dev_attr_debug.attr, ++ NULL, ++}; ++ ++static const struct attribute_group i2c_ft_device_group = { ++ .attrs = i2c_ft_device_attrs, ++}; ++ ++#ifdef CONFIG_ACPI ++static void i2c_phyt_acpi_params(struct platform_device *pdev, char method[], ++ u16 *hcnt, u16 *lcnt, u32 *sda_hold) ++{ ++ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; ++ acpi_handle handle = ACPI_HANDLE(&pdev->dev); ++ union acpi_object *obj; ++ ++ if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf))) ++ return; ++ ++ obj = (union acpi_object *)buf.pointer; ++ if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) { ++ const union acpi_object *objs = obj->package.elements; ++ ++ *hcnt = (u16)objs[0].integer.value; ++ *lcnt = (u16)objs[1].integer.value; ++ *sda_hold = (u32)objs[2].integer.value; ++ } ++ ++ kfree(buf.pointer); ++} ++ ++static int i2c_phyt_acpi_configure(struct platform_device *pdev) ++{ ++ struct i2c_phyt_dev *dev = platform_get_drvdata(pdev); ++ struct i2c_timings *t = &dev->timings; ++ u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0; ++ const struct acpi_device_id *id; ++ ++ dev->adapter.nr = -1; ++ ++ /* ++ * Try to get SDA hold time and *CNT values from an ACPI method for ++ * selected speed modes. ++ */ ++ i2c_phyt_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht); ++ i2c_phyt_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht); ++ i2c_phyt_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht); ++ i2c_phyt_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); ++ ++ switch (t->bus_freq_hz) { ++ case FT_I2C_SPEED_100K: ++ dev->sda_hold_time = ss_ht; ++ break; ++ case FT_I2C_SPEED_1000K: ++ dev->sda_hold_time = fp_ht; ++ break; ++ case FT_I2C_SPEED_3400K: ++ dev->sda_hold_time = hs_ht; ++ break; ++ case FT_I2C_SPEED_400K: ++ default: ++ dev->sda_hold_time = fs_ht; ++ break; ++ } ++ ++ id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); ++ if (id && id->driver_data) ++ dev->flags |= (u32)id->driver_data; ++ ++ return 0; ++} ++ ++static const struct acpi_device_id i2c_phyt_acpi_match[] = { ++ { "PHYT0059", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, i2c_phyt_acpi_match); ++#else ++static inline int i2c_phyt_acpi_configure(struct platform_device *pdev) ++{ ++ return -ENODEV; ++} ++#endif ++ ++static void i2c_phyt_configure_master(struct i2c_phyt_dev *dev) ++{ ++ struct i2c_timings *t = &dev->timings; ++ ++ dev->functionality = I2C_FUNC_10BIT_ADDR | FT_IC_DEFAULT_FUNCTIONALITY; ++ ++ dev->master_cfg = FT_IC_CON_MASTER | FT_IC_CON_SLAVE_DISABLE | ++ FT_IC_CON_RESTART_EN; ++ ++ dev->mode = phyt_IC_MASTER; ++ ++ switch (t->bus_freq_hz) { ++ case FT_I2C_SPEED_100K: ++ dev->master_cfg |= FT_IC_CON_SPEED_STD; ++ break; ++ case FT_I2C_SPEED_3400K: ++ dev->master_cfg |= FT_IC_CON_SPEED_HIGH; ++ break; ++ default: ++ dev->master_cfg |= FT_IC_CON_SPEED_FAST; ++ } ++} ++ ++static void i2c_phyt_configure_slave(struct i2c_phyt_dev *dev) ++{ ++ dev->functionality = I2C_FUNC_SLAVE | FT_IC_DEFAULT_FUNCTIONALITY; ++ ++ dev->slave_cfg = FT_IC_CON_RX_FIFO_FULL_HLD_CTRL | ++ FT_IC_CON_RESTART_EN | FT_IC_CON_STOP_DET_IFADDRESSED; ++ ++ dev->mode = phyt_IC_SLAVE; ++} ++ ++ ++static void i2c_phyt_timer_handle(struct timer_list *t) ++{ ++ struct i2c_phyt_dev *dev = from_timer(dev, t, timer); ++ ++ if (dev->alive_enabled && dev->watchdog) ++ dev->watchdog(dev); ++ ++ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(2000)); ++} ++ ++static int i2c_phyt_plat_probe(struct platform_device *pdev) ++{ ++ struct i2c_adapter *adap; ++ struct i2c_phyt_dev *dev; ++ struct i2c_timings *t; ++ u32 acpi_speed; ++ struct resource *reg_mem, *share_mem; ++ int irq, ret, i; ++ static const int supported_speeds[] = { ++ 0, FT_I2C_SPEED_100K, FT_I2C_SPEED_400K, FT_I2C_SPEED_1000K, FT_I2C_SPEED_3400K ++ }; ++ ++ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (irq < 0) { ++ dev_err(&pdev->dev, "Err:irq :%d,exit\n", irq); ++ return irq; ++ } ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(struct i2c_phyt_dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->irq = irq; ++ /*find regfile info*/ ++ reg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!reg_mem) { ++ dev_err(&pdev->dev, "Err:can't find valid regfile mem,exit\n"); ++ return -ENOMEM; ++ } ++ /*get regfile base address*/ ++ dev->base = devm_ioremap_resource(&pdev->dev, reg_mem); ++ if (IS_ERR(dev->base)) { ++ dev_err(&pdev->dev, "dev->base is err exit\n"); ++ return PTR_ERR(dev->base); ++ } ++ /*find share mem info*/ ++ share_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!share_mem) { ++ dev_err(&pdev->dev, "Err:can't find valid shmem,exit\n"); ++ return -ENOMEM; ++ } ++ ++ /*set tx share mem start addr*/ ++ dev->tx_shmem_addr = devm_ioremap_wc(&pdev->dev, share_mem->start, ++ resource_size(share_mem)); ++ if (IS_ERR(dev->tx_shmem_addr)) { ++ dev_err(&pdev->dev, "tx_shmem_addr is err\n"); ++ return PTR_ERR(dev->tx_shmem_addr); ++ } ++ ++ /*set rx share mem start addr*/ ++ dev->mng.tx_ring_cnt = (i2c_phyt_read_reg(dev, FT_I2C_REGFILE_RING) & ++ FT_I2C_REGFILE_TX_RING_MASK) >> FT_I2C_REGFILE_TX_RING_OFFSET; ++ if (!dev->mng.tx_ring_cnt || (dev->mng.tx_ring_cnt > 8)) { ++ dev_err(&pdev->dev, "failed set tx ring cnt:%d\n", dev->mng.tx_ring_cnt); ++ return -EINVAL; ++ } ++ dev->rx_shmem_addr = dev->tx_shmem_addr + ++ dev->mng.tx_ring_cnt * sizeof(struct phyt_msg_info); ++ ++ dev->dev = &pdev->dev; ++ platform_set_drvdata(pdev, dev); ++ ++ ret = i2c_phyt_malloc_log_mem(dev); ++ if (ret) ++ return -ENOMEM; ++ ++ dev->timer.expires = jiffies + msecs_to_jiffies(3000); ++ timer_setup(&dev->timer, i2c_phyt_timer_handle, 0); ++ add_timer(&dev->timer); ++ ++ dev->watchdog = i2c_phyt_common_watchdog; ++ ++ i2c_phyt_disable_debug(dev); ++ dev->debug_enabled = false; ++ ++ dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(dev->rst)) { ++ if (PTR_ERR(dev->rst) == -EPROBE_DEFER) { ++ dev_err(&pdev->dev, "dev rst not null\n"); ++ return -EPROBE_DEFER; ++ } ++ } else { ++ reset_control_deassert(dev->rst); ++ } ++ ++ t = &dev->timings; ++ i2c_parse_fw_timings(&pdev->dev, t, false); ++ ++ acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev); ++ ++ /* ++ * Some DSTDs use a non standard speed, round down to the lowest ++ * standard speed. ++ */ ++ for (i = 1; i < ARRAY_SIZE(supported_speeds); i++) { ++ if (acpi_speed < supported_speeds[i]) ++ break; ++ } ++ acpi_speed = supported_speeds[i - 1]; ++ ++ /* ++ * Find bus speed from the "clock-frequency" device property, ACPI ++ * or by using fast mode if neither is set. ++ */ ++ if (acpi_speed && t->bus_freq_hz) ++ t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed); ++ else if (acpi_speed || t->bus_freq_hz) ++ t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); ++ else ++ t->bus_freq_hz = FT_I2C_SPEED_400K; ++ ++ if (has_acpi_companion(&pdev->dev)) ++ i2c_phyt_acpi_configure(pdev); ++ ++ /* ++ * Only standard mode at 100kHz, fast mode at 400kHz, ++ * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported. ++ */ ++ if (t->bus_freq_hz != FT_I2C_SPEED_100K && t->bus_freq_hz != FT_I2C_SPEED_400K && ++ t->bus_freq_hz != FT_I2C_SPEED_1000K && t->bus_freq_hz != FT_I2C_SPEED_3400K) { ++ dev_err(&pdev->dev, ++ "%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n", ++ t->bus_freq_hz); ++ ret = -EINVAL; ++ goto exit_reset; ++ } ++ ++ if (i2c_detect_slave_mode(&pdev->dev)) ++ i2c_phyt_configure_slave(dev); ++ else ++ i2c_phyt_configure_master(dev); ++ ++ dev->clk = devm_clk_get(&pdev->dev, NULL); ++ ++ if (!i2c_phyt_prepare_clk(dev, true)) { ++ u64 clk_khz; ++ ++ dev->get_clk_rate_khz = i2c_phyt_get_clk_rate_khz; ++ clk_khz = dev->get_clk_rate_khz(dev); ++ ++ if (!dev->sda_hold_time && t->sda_hold_ns) ++ dev->sda_hold_time = ++ div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000); ++ } ++ ++ dev->adapter.nr = pdev->id; ++ ++ adap = &dev->adapter; ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_DEPRECATED; ++ ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); ++ adap->dev.of_node = pdev->dev.of_node; ++ adap->timeout = HZ; ++ adap->dev.fwnode = pdev->dev.fwnode; ++ dev_pm_set_driver_flags(&pdev->dev, ++ DPM_FLAG_SMART_PREPARE | ++ DPM_FLAG_SMART_SUSPEND | ++ DPM_FLAG_MAY_SKIP_RESUME); ++ ++ /* The code below assumes runtime PM to be disabled. */ ++ WARN_ON(pm_runtime_enabled(&pdev->dev)); ++ ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_set_active(&pdev->dev); ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ if (dev->mode == phyt_IC_SLAVE) ++ ret = i2c_phyt_slave_probe(dev); ++ else ++ ret = i2c_phyt_master_probe(dev); ++ ++ if (ret) ++ goto exit_probe; ++ ++ if (sysfs_create_group(&dev->dev->kobj, &i2c_ft_device_group)) ++ dev_warn(&pdev->dev, "failed create sysfs\n"); ++ ++ i2c_phyt_enable_alive(dev); ++ dev->alive_enabled = true; ++ ++ return ret; ++ ++exit_probe: ++ pm_runtime_disable(dev->dev); ++exit_reset: ++ del_timer(&dev->timer); ++ if (!IS_ERR_OR_NULL(dev->rst)) ++ reset_control_assert(dev->rst); ++ return ret; ++} ++ ++static int i2c_phyt_plat_remove(struct platform_device *pdev) ++{ ++ struct i2c_phyt_dev *dev = platform_get_drvdata(pdev); ++ ++ dev_info(&pdev->dev, "i2c_2.0 remove\n"); ++ pm_runtime_get_sync(&pdev->dev); ++ ++ i2c_del_adapter(&dev->adapter); ++ sysfs_remove_group(&dev->dev->kobj, &i2c_ft_device_group); ++ dev->disable(dev); ++ /*disable alive function*/ ++ i2c_phyt_disable_alive(dev); ++ del_timer(&dev->timer); ++ ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(dev->dev); ++ ++ if (!IS_ERR_OR_NULL(dev->rst)) ++ reset_control_assert(dev->rst); ++ ++ i2c_phyt_common_regfile_disable_int(dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_OF ++static const struct of_device_id i2c_phyt_of_match[] = { ++ { .compatible = "phytium,i2c-2.0", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, i2c_phyt_of_match); ++#endif ++ ++static int __maybe_unused i2c_phyt_plat_suspend(struct device *dev) ++{ ++ struct i2c_phyt_dev *idev = dev_get_drvdata(dev); ++ ++ idev->disable(idev); ++ ++ i2c_phyt_disable_alive(idev); ++ idev->alive_enabled = false; ++ ++ i2c_phyt_prepare_clk(idev, false); ++ ++ return 0; ++} ++ ++static int __maybe_unused i2c_phyt_plat_resume(struct device *dev) ++{ ++ struct i2c_phyt_dev *idev = dev_get_drvdata(dev); ++ ++ i2c_phyt_prepare_clk(idev, true); ++ idev->init(idev); ++ ++ i2c_phyt_enable_alive(idev); ++ idev->alive_enabled = true; ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops i2c_phyt_dev_pm_ops = { ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_phyt_plat_suspend, ++ i2c_phyt_plat_resume) ++ SET_RUNTIME_PM_OPS(i2c_phyt_plat_suspend, ++ i2c_phyt_plat_resume, NULL) ++}; ++ ++static struct platform_driver i2c_phyt_driver = { ++ .probe = i2c_phyt_plat_probe, ++ .remove = i2c_phyt_plat_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = of_match_ptr(i2c_phyt_of_match), ++ .acpi_match_table = ACPI_PTR(i2c_phyt_acpi_match), ++ .pm = &i2c_phyt_dev_pm_ops, ++ }, ++}; ++module_platform_driver(i2c_phyt_driver); ++ ++MODULE_ALIAS("platform:i2c-2.0"); ++MODULE_AUTHOR("Wu Jinyong "); ++MODULE_DESCRIPTION("Phytium I2C bus adapter"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(I2C_PHYTIUM_V2_DRV_VERSION); +diff --git a/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-slave.c b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-slave.c +new file mode 100644 +index 000000000000..5675a1974fbe +--- /dev/null ++++ b/drivers/i2c/busses/phytium_i2c_v2/i2c-phyt-slave.c +@@ -0,0 +1,283 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Phytium I2C adapter driver (slave only). ++ * ++ * Copyright (C) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "i2c-phyt-core.h" ++ ++#define FT_I2C_RX_FIFO_FULL_ENABLE 1 ++#define FT_I2C_RX_FIFO_FULL_DISABLE 0 ++ ++#define FT_I2C_CON_STOP_DET_IFADDR_ENABLE 1 ++#define FT_I2C_CON_STOP_DET_IFADDR_DISABLE 0 ++ ++#define FT_I2C_SLAVE_EVNET_MAX_CNT 56 ++#define FT_I2C_SLAVE_DATA_INDEX(index) (index+1) ++/*one is cmd,the next one is data*/ ++#define FT_I2C_SLAVE_RX_INFO_SIZE 2 ++ ++int i2c_phyt_slave_event_process(struct i2c_phyt_dev *dev, ++ struct phyt_msg_info *rx_msg, u32 rx_head, u32 rx_tail) ++{ ++ u8 buf[32] = {1}; ++ u32 head = rx_head, tail = rx_tail; ++ ++ if (!dev || !dev->slave) { ++ dev_err(dev->dev, "dev is null\n"); ++ return -ENXIO; ++ } ++ ++ if ((head >= FT_I2C_SLAVE_EVNET_MAX_CNT) || (tail >= FT_I2C_SLAVE_EVNET_MAX_CNT)) { ++ dev_err(dev->dev, "head:%d, tail:%d\n", head, tail); ++ return -EINVAL; ++ } ++ ++ while (head != tail) { ++ if (head % FT_I2C_SLAVE_RX_INFO_SIZE) ++ head++; ++ ++ i2c_slave_event(dev->slave, rx_msg->data[head], ++ &(rx_msg->data[FT_I2C_SLAVE_DATA_INDEX(head)])); ++ /*send the read data to RV*/ ++ if ((rx_msg->data[head] == I2C_SLAVE_READ_REQUESTED) || ++ (rx_msg->data[head] == I2C_SLAVE_READ_PROCESSED)) { ++ /*buf[0] is used to stor size,and fixed to 1*/ ++ buf[1] = rx_msg->data[FT_I2C_SLAVE_DATA_INDEX(head)]; ++ i2c_phyt_data_cmd8_array(dev, PHYTI2C_MSG_CMD_DATA_SLAVE, ++ buf, 2); ++ } ++ head += FT_I2C_SLAVE_RX_INFO_SIZE; ++ if (head >= FT_I2C_SLAVE_EVNET_MAX_CNT) ++ head = 0; ++ } ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_HEAD, head); ++ ++ return 0; ++} ++ ++static irqreturn_t i2c_phyt_slave_regfile_isr(int this_irq, void *dev_id) ++{ ++ u32 stat; ++ struct i2c_phyt_dev *dev = (struct i2c_phyt_dev *)dev_id; ++ ++ stat = i2c_phyt_read_reg(dev, FT_I2C_REGFILE_RV2AP_INTR_STAT); ++ ++ if (!(stat & FT_I2C_RV2AP_INTR_BIT4)) { ++ dev_warn(dev->dev, "intr stat=%#x\n", stat); ++ return IRQ_NONE; ++ } ++ ++ i2c_phyt_common_regfile_clear_rv2ap_int(dev, stat); ++ ++ if (dev->complete_flag) { ++ dev->complete_flag = false; ++ complete(&dev->cmd_complete); ++ } else { ++ i2c_phyt_slave_isr_handle(dev); ++ i2c_phyt_show_log(dev); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int i2c_phyt_slave_init(struct i2c_phyt_dev *dev) ++{ ++ u8 slave_mode = FT_I2C_MASTER_MODE_FLAG; ++ u8 rx_fifo_full_en = FT_I2C_RX_FIFO_FULL_DISABLE; ++ u8 stop_det_ifaddr_en = FT_I2C_CON_STOP_DET_IFADDR_DISABLE; ++ int ret; ++ ++ i2c_phyt_set_module_en(dev, FT_I2C_ADAPTER_MODULE_OFF); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set module off: %d\n", ret); ++ return ret; ++ } ++ ++ if (dev->sda_hold_time) { ++ i2c_phyt_set_sda_hold(dev, dev->sda_hold_time); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set sda hold time: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ /*set slave mode*/ ++ if ((dev->mode & FT_I2C_CON_MASTER_MODE_MASK) == phyt_IC_SLAVE) ++ slave_mode = FT_I2C_SLAVE_MODE_FLAG; ++ else { ++ dev_err(dev->dev, "dev is not in slave mode\n"); ++ return -EINVAL; ++ } ++ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_MODE, slave_mode); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set mode: %d\n", ret); ++ return ret; ++ } ++ ++ i2c_phyt_set_int_tl(dev, 0, 0); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set int tl: %d\n", ret); ++ return ret; ++ } ++ ++ if ((dev->slave_cfg & FT_I2C_CON_RX_FIFO_FULL_HLD_MASK) == ++ FT_IC_CON_RX_FIFO_FULL_HLD_CTRL) ++ rx_fifo_full_en = FT_I2C_RX_FIFO_FULL_ENABLE; ++ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_RX_FIFO_FULL, rx_fifo_full_en); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set rx fifo full: %d\n", ret); ++ return ret; ++ } ++ ++ if ((dev->slave_cfg & FT_I2C_CON_STOP_DET_IFADDR_MASK) == FT_IC_CON_STOP_DET_IFADDRESSED) ++ stop_det_ifaddr_en = FT_I2C_CON_STOP_DET_IFADDR_ENABLE; ++ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_STOP_DET_IF_ADDRESSED, ++ stop_det_ifaddr_en); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set stop det ifaddr: %d\n", ret); ++ return ret; ++ } ++ i2c_phyt_set_int_interrupt(dev, FT_I2C_ENABLE_INTERRUPT, FT_IC_INTR_SLAVE_MASK); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set interrupt: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int i2c_phyt_reg_slave(struct i2c_client *slave) ++{ ++ int ret; ++ struct i2c_phyt_dev *dev = i2c_get_adapdata(slave->adapter); ++ ++ if (dev->slave) ++ return -EBUSY; ++ if (slave->flags & I2C_CLIENT_TEN) ++ return -EAFNOSUPPORT; ++ ++ pm_runtime_get_sync(dev->dev); ++ ++ /* ++ * Set slave address in the IC_SAR register, ++ * the address to which the i2c responds. ++ */ ++ i2c_phyt_set_module_en(dev, FT_I2C_ADAPTER_MODULE_OFF); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set module off: %d\n", ret); ++ return ret; ++ } ++ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_ADDR_MODE, FT_I2C_ADDR_7BIT_MODE); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set addr mode: %d\n", ret); ++ return ret; ++ } ++ ++ i2c_phyt_set_cmd8(dev, PHYTI2C_MSG_CMD_SET_ADDR, slave->addr); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set addr: %d\n", ret); ++ return ret; ++ } ++ ++ dev->slave = slave; ++ ++ i2c_phyt_set_module_en(dev, FT_I2C_ADAPTER_MODULE_ON); ++ ret = i2c_phyt_check_result(dev); ++ if (ret) { ++ dev_err(dev->dev, "fail to set module on: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int i2c_phyt_unreg_slave(struct i2c_client *slave) ++{ ++ struct i2c_phyt_dev *dev = i2c_get_adapdata(slave->adapter); ++ ++ dev->disable_int(dev); ++ dev->disable(dev); ++ dev->slave = NULL; ++ pm_runtime_put(dev->dev); ++ ++ return 0; ++} ++ ++static const struct i2c_algorithm i2c_phyt_slave_algo = { ++ .functionality = i2c_phyt_func, ++ .reg_slave = i2c_phyt_reg_slave, ++ .unreg_slave = i2c_phyt_unreg_slave, ++}; ++ ++ ++int i2c_phyt_slave_probe(struct i2c_phyt_dev *dev) ++{ ++ struct i2c_adapter *adap = &dev->adapter; ++ int ret; ++ ++ init_completion(&dev->cmd_complete); ++ ++ i2c_phyt_common_regfile_disable_int(dev); ++ i2c_phyt_common_regfile_clear_rv2ap_int(dev, 0); ++ ++ ret = devm_request_irq(dev->dev, dev->irq, i2c_phyt_slave_regfile_isr, IRQF_SHARED, ++ dev_name(dev->dev), dev); ++ if (ret) { ++ dev_err(dev->dev, "failure requesting irq %i: %d\n", ++ dev->irq, ret); ++ return ret; ++ } ++ ++ i2c_phyt_common_regfile_enable_int(dev); ++ ++ dev->init = i2c_phyt_slave_init; ++ dev->disable = i2c_phyt_disable; ++ dev->disable_int = i2c_phyt_disable_int; ++ ++ snprintf(adap->name, sizeof(adap->name), ++ "Phytium I2C_2.0 Slave adapter"); ++ adap->retries = 3; ++ adap->algo = &i2c_phyt_slave_algo; ++ adap->dev.parent = dev->dev; ++ ++ ret = i2c_phyt_slave_init(dev); ++ if (ret) ++ return ret; ++ ++ i2c_phyt_write_reg(dev, FT_I2C_REGFILE_HEAD, 0); ++ i2c_set_adapdata(adap, dev); ++ ++ ret = i2c_add_numbered_adapter(adap); ++ if (ret) ++ dev_err(dev->dev, "failure adding adapter: %d\n", ret); ++ ++ dev_info(dev->dev, "i2c_2.0 slave probe ok\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(i2c_phyt_slave_probe); +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +index bc4cbc7542ce..659e03144998 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +@@ -162,6 +162,18 @@ static void queue_inc_cons(struct arm_smmu_ll_queue *q) + q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); + } + ++static void queue_sync_cons_ovf(struct arm_smmu_queue *q) ++{ ++ struct arm_smmu_ll_queue *llq = &q->llq; ++ ++ if (likely(Q_OVF(llq->prod) == Q_OVF(llq->cons))) ++ return; ++ ++ llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | ++ Q_IDX(llq, llq->cons); ++ queue_sync_cons_out(q); ++} ++ + static int queue_sync_prod_in(struct arm_smmu_queue *q) + { + u32 prod; +@@ -1380,8 +1392,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) + } while (!queue_empty(llq)); + + /* Sync our overflow flag, as we believe we're up to speed */ +- llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | +- Q_IDX(llq, llq->cons); ++ queue_sync_cons_ovf(q); + return IRQ_HANDLED; + } + +@@ -1439,9 +1450,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) + } while (!queue_empty(llq)); + + /* Sync our overflow flag, as we believe we're up to speed */ +- llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | +- Q_IDX(llq, llq->cons); +- queue_sync_cons_out(q); ++ queue_sync_cons_ovf(q); + return IRQ_HANDLED; + } + +@@ -2864,6 +2873,13 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) + doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo; + doorbell &= MSI_CFG0_ADDR_MASK; + ++#ifdef CONFIG_PM_SLEEP ++ /* Saves the msg (base addr of msi irq) and restores it during resume */ ++ desc->msg.address_lo = msg->address_lo; ++ desc->msg.address_hi = msg->address_hi; ++ desc->msg.data = msg->data; ++#endif ++ + writeq_relaxed(doorbell, smmu->base + cfg[0]); + writel_relaxed(msg->data, smmu->base + cfg[1]); + writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]); +@@ -2919,11 +2935,51 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu) + devm_add_action(dev, arm_smmu_free_msis, dev); + } + +-static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) ++#ifdef CONFIG_PM_SLEEP ++static void arm_smmu_resume_msis(struct arm_smmu_device *smmu) ++{ ++ struct msi_desc *desc; ++ struct device *dev = smmu->dev; ++ ++ for_each_msi_entry(desc, dev) { ++ switch (desc->platform.msi_index) { ++ case EVTQ_MSI_INDEX: ++ case GERROR_MSI_INDEX: ++ case PRIQ_MSI_INDEX: { ++ phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index]; ++ struct msi_msg *msg = &desc->msg; ++ phys_addr_t doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo; ++ ++ doorbell &= MSI_CFG0_ADDR_MASK; ++ writeq_relaxed(doorbell, smmu->base + cfg[0]); ++ writel_relaxed(msg->data, smmu->base + cfg[1]); ++ writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, ++ smmu->base + cfg[2]); ++ break; ++ } ++ default: ++ continue; ++ ++ } ++ } ++} ++#else ++static void arm_smmu_resume_msis(struct arm_smmu_device *smmu) ++{ ++} ++#endif ++ ++static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu, bool resume) + { + int irq, ret; + +- arm_smmu_setup_msis(smmu); ++ if (!resume) ++ arm_smmu_setup_msis(smmu); ++ else { ++ /* The irq doesn't need to be re-requested during resume */ ++ arm_smmu_resume_msis(smmu); ++ return; ++ } + + /* Request interrupt lines */ + irq = smmu->evtq.q.irq; +@@ -2965,7 +3021,7 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) + } + } + +-static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) ++static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu, bool resume) + { + int ret, irq; + u32 irqen_flags = IRQ_CTRL_EVTQ_IRQEN | IRQ_CTRL_GERROR_IRQEN; +@@ -2992,7 +3048,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) + if (ret < 0) + dev_warn(smmu->dev, "failed to enable combined irq\n"); + } else +- arm_smmu_setup_unique_irqs(smmu); ++ arm_smmu_setup_unique_irqs(smmu, resume); + + if (smmu->features & ARM_SMMU_FEAT_PRI) + irqen_flags |= IRQ_CTRL_PRIQ_IRQEN; +@@ -3017,7 +3073,7 @@ static int arm_smmu_device_disable(struct arm_smmu_device *smmu) + return ret; + } + +-static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) ++static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume) + { + int ret; + u32 reg, enables; +@@ -3125,7 +3181,7 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) + } + } + +- ret = arm_smmu_setup_irqs(smmu); ++ ret = arm_smmu_setup_irqs(smmu, resume); + if (ret) { + dev_err(smmu->dev, "failed to setup irqs\n"); + return ret; +@@ -3135,7 +3191,7 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) + enables &= ~(CR0_EVTQEN | CR0_PRIQEN); + + /* Enable the SMMU interface, or ensure bypass */ +- if (!bypass || disable_bypass) { ++ if (!smmu->bypass || disable_bypass) { + enables |= CR0_SMMUEN; + } else { + ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT); +@@ -3483,6 +3539,26 @@ static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start, + return devm_ioremap_resource(dev, &res); + } + ++#ifdef CONFIG_PM_SLEEP ++static int arm_smmu_suspend(struct device *dev) ++{ ++ /* ++ * The smmu is powered off and related registers are automatically ++ * cleared when suspend. No need to do anything. ++ */ ++ return 0; ++} ++ ++static int arm_smmu_resume(struct device *dev) ++{ ++ struct arm_smmu_device *smmu = dev_get_drvdata(dev); ++ ++ arm_smmu_device_reset(smmu, true); ++ ++ return 0; ++} ++#endif ++ + static int arm_smmu_device_probe(struct platform_device *pdev) + { + int irq, ret; +@@ -3490,7 +3566,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev) + resource_size_t ioaddr; + struct arm_smmu_device *smmu; + struct device *dev = &pdev->dev; +- bool bypass; + + smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); + if (!smmu) { +@@ -3508,7 +3583,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev) + } + + /* Set bypass mode according to firmware probing result */ +- bypass = !!ret; ++ smmu->bypass = !!ret; + + /* Base address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -3569,7 +3644,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, smmu); + + /* Reset the device */ +- ret = arm_smmu_device_reset(smmu, bypass); ++ ret = arm_smmu_device_reset(smmu, false); + if (ret) + return ret; + +@@ -3614,10 +3689,21 @@ static const struct of_device_id arm_smmu_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, arm_smmu_of_match); + ++#ifdef CONFIG_PM_SLEEP ++static const struct dev_pm_ops arm_smmu_pm_ops = { ++ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(arm_smmu_suspend, ++ arm_smmu_resume) ++}; ++#define ARM_SMMU_PM_OPS (&arm_smmu_pm_ops) ++#else ++#define ARM_SMMU_PM_OPS NULL ++#endif ++ + static struct platform_driver arm_smmu_driver = { + .driver = { + .name = "arm-smmu-v3", + .of_match_table = arm_smmu_of_match, ++ .pm = ARM_SMMU_PM_OPS, + .suppress_bind_attrs = true, + }, + .probe = arm_smmu_device_probe, +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +index 57e5d223c467..bc95e4773ead 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +@@ -636,6 +636,7 @@ struct arm_smmu_device { + + /* IOMMU core code handle */ + struct iommu_device iommu; ++ bool bypass; + }; + + /* SMMU private data for each master */ +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 0cc983acafca..c2e677a14d40 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -112,6 +112,16 @@ config PHANTOM + If you choose to build module, its name will be phantom. If unsure, + say N here. + ++config PHYTIUM_SNOOP_CTRL ++ tristate "Phytium snoop controller support" ++ depends on ARCH_PHYTIUM && REGMAP && MFD_SYSCON ++ default n ++ help ++ Say Y here if you want BMC to snoop 80h port. ++ Provides a driver to control the phytium snoop interface which ++ allows the BMC to listen on and save the data written by the ++ host to an arbitrary I/O port. ++ + config INTEL_MID_PTI + tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard" + depends on PCI && TTY && (X86_INTEL_MID || COMPILE_TEST) +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 0d495fbc8f26..7813f5dde90a 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -17,7 +17,7 @@ obj-$(CONFIG_LKDTM) += lkdtm/ + obj-$(CONFIG_TIFM_CORE) += tifm_core.o + obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o + obj-$(CONFIG_PHANTOM) += phantom.o +-obj-$(CONFIG_PHYTIUM_LPC_SNOOP) += phytium-lpc-snoop.o ++obj-$(CONFIG_PHYTIUM_SNOOP_CTRL) += phytium-snoop-ctrl.o + obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o + obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o + obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o +diff --git a/drivers/misc/phytium-lpc-snoop.c b/drivers/misc/phytium-snoop-ctrl.c +similarity index 58% +rename from drivers/misc/phytium-lpc-snoop.c +rename to drivers/misc/phytium-snoop-ctrl.c +index d7caa93d20b3..aedb15bbfa5f 100644 +--- a/drivers/misc/phytium-lpc-snoop.c ++++ b/drivers/misc/phytium-snoop-ctrl.c +@@ -5,9 +5,9 @@ + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * +- * Provides a simple driver to control the PHYTIUM LPC snoop interface which ++ * Provides a simple driver to control the PHYTIUM snoop ctrl interface which + * allows the BMC to listen on and save the data written by +- * the host to an arbitrary LPC I/O port. ++ * the host to an arbitrary I/O port. + * + * Typically used by the BMC to "watch" host boot progress via port + * 0x80 writes made by the BIOS during the boot process. +@@ -29,7 +29,7 @@ + #include + #include + +-#define DEVICE_NAME "phytium-lpc-snoop" ++#define DEVICE_NAME "phytium-snoop-ctrl" + + #define NUM_SNOOP_CHANNELS 2 + #define SNOOP_FIFO_SIZE 2048 +@@ -56,29 +56,31 @@ + #define snp_data_reg_snp2_data_reg GENMASK(15, 8) + #define snp_data_reg_snp2_shift 8 + +-struct phytium_lpc_snoop_channel { ++#define SNOOP_DRIVER_VERSION "1.1.1" ++ ++struct phytium_snoop_ctrl_channel { + struct kfifo fifo; + wait_queue_head_t wq; + struct miscdevice miscdev; + }; + +-struct phytium_lpc_snoop { ++struct phytium_snoop_ctrl { + struct regmap *regmap; + int irq; +- struct phytium_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; ++ struct phytium_snoop_ctrl_channel chan[NUM_SNOOP_CHANNELS]; + }; + +-static struct phytium_lpc_snoop_channel *snoop_file_to_chan(struct file *file) ++static struct phytium_snoop_ctrl_channel *snoop_file_to_chan(struct file *file) + { + return container_of(file->private_data, +- struct phytium_lpc_snoop_channel, ++ struct phytium_snoop_ctrl_channel, + miscdev); + } + + static ssize_t snoop_file_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) + { +- struct phytium_lpc_snoop_channel *chan = snoop_file_to_chan(file); ++ struct phytium_snoop_ctrl_channel *chan = snoop_file_to_chan(file); + unsigned int copied; + int ret = 0; + +@@ -98,7 +100,7 @@ static ssize_t snoop_file_read(struct file *file, char __user *buffer, + static unsigned int snoop_file_poll(struct file *file, + struct poll_table_struct *pt) + { +- struct phytium_lpc_snoop_channel *chan = snoop_file_to_chan(file); ++ struct phytium_snoop_ctrl_channel *chan = snoop_file_to_chan(file); + + poll_wait(file, &chan->wq, pt); + return !kfifo_is_empty(&chan->fifo) ? POLLIN : 0; +@@ -112,7 +114,7 @@ static const struct file_operations snoop_fops = { + }; + + /* Save a byte to a FIFO and discard the oldest byte if FIFO is full */ +-static void put_fifo_with_discard(struct phytium_lpc_snoop_channel *chan, u8 val) ++static void put_fifo_with_discard(struct phytium_snoop_ctrl_channel *chan, u8 val) + { + if (!kfifo_initialized(&chan->fifo)) + return; +@@ -122,12 +124,12 @@ static void put_fifo_with_discard(struct phytium_lpc_snoop_channel *chan, u8 val + wake_up_interruptible(&chan->wq); + } + +-static irqreturn_t phytium_lpc_snoop_irq(int irq, void *arg) ++static irqreturn_t phytium_snoop_ctrl_irq(int irq, void *arg) + { +- struct phytium_lpc_snoop *lpc_snoop = arg; ++ struct phytium_snoop_ctrl *snoop_ctrl = arg; + u32 reg, data; + +- if (regmap_read(lpc_snoop->regmap, snp_status_reg, ®)) ++ if (regmap_read(snoop_ctrl->regmap, snp_status_reg, ®)) + return IRQ_NONE; + + /* Check if one of the snoop channels is interrupting */ +@@ -136,71 +138,71 @@ static irqreturn_t phytium_lpc_snoop_irq(int irq, void *arg) + return IRQ_NONE; + + /* Ack pending IRQs */ +- regmap_write(lpc_snoop->regmap, snp_status_reg, reg); ++ regmap_write(snoop_ctrl->regmap, snp_status_reg, reg); + + /* Read and save most recent snoop'ed data byte to FIFO */ +- regmap_read(lpc_snoop->regmap, snp_data_reg, &data); ++ regmap_read(snoop_ctrl->regmap, snp_data_reg, &data); + + if (reg & snp_status_reg_snp1_int) { + u8 val = (data & snp_data_reg_snp1_data_reg) >> snp_data_reg_snp1_shift; + +- put_fifo_with_discard(&lpc_snoop->chan[0], val); ++ put_fifo_with_discard(&snoop_ctrl->chan[0], val); + } + if (reg & snp_status_reg_snp2_int) { + u8 val = (data & snp_data_reg_snp2_data_reg) >> snp_data_reg_snp2_shift; + +- put_fifo_with_discard(&lpc_snoop->chan[1], val); ++ put_fifo_with_discard(&snoop_ctrl->chan[1], val); + } + + return IRQ_HANDLED; + } + +-static int phytium_lpc_snoop_config_irq(struct phytium_lpc_snoop *lpc_snoop, ++static int phytium_snoop_ctrl_config_irq(struct phytium_snoop_ctrl *snoop_ctrl, + struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + int rc; + +- lpc_snoop->irq = platform_get_irq(pdev, 0); +- if (!lpc_snoop->irq) ++ snoop_ctrl->irq = platform_get_irq(pdev, 0); ++ if (!snoop_ctrl->irq) + return -ENODEV; + +- rc = devm_request_irq(dev, lpc_snoop->irq, +- phytium_lpc_snoop_irq, IRQF_SHARED, +- DEVICE_NAME, lpc_snoop); ++ rc = devm_request_irq(dev, snoop_ctrl->irq, ++ phytium_snoop_ctrl_irq, IRQF_SHARED, ++ DEVICE_NAME, snoop_ctrl); + if (rc < 0) { +- dev_warn(dev, "Unable to request IRQ %d\n", lpc_snoop->irq); +- lpc_snoop->irq = 0; ++ dev_warn(dev, "Unable to request IRQ %d\n", snoop_ctrl->irq); ++ snoop_ctrl->irq = 0; + return rc; + } + + return 0; + } + +-static int phytium_lpc_enable_snoop(struct phytium_lpc_snoop *lpc_snoop, ++static int phytium_enable_snoop(struct phytium_snoop_ctrl *snoop_ctrl, + struct device *dev, +- int channel, u16 lpc_port) ++ int channel, u16 snoop_port) + { + int rc = 0; + u32 snp_enable_reg_en, snp_addr_reg_mask, snp_addr_reg_shift; + +- init_waitqueue_head(&lpc_snoop->chan[channel].wq); ++ init_waitqueue_head(&snoop_ctrl->chan[channel].wq); + /* Create FIFO datastructure */ +- rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo, ++ rc = kfifo_alloc(&snoop_ctrl->chan[channel].fifo, + SNOOP_FIFO_SIZE, GFP_KERNEL); + if (rc) + return rc; + +- lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; +- lpc_snoop->chan[channel].miscdev.name = ++ snoop_ctrl->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; ++ snoop_ctrl->chan[channel].miscdev.name = + devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel); +- lpc_snoop->chan[channel].miscdev.fops = &snoop_fops; +- lpc_snoop->chan[channel].miscdev.parent = dev; +- rc = misc_register(&lpc_snoop->chan[channel].miscdev); ++ snoop_ctrl->chan[channel].miscdev.fops = &snoop_fops; ++ snoop_ctrl->chan[channel].miscdev.parent = dev; ++ rc = misc_register(&snoop_ctrl->chan[channel].miscdev); + if (rc) + return rc; + +- /* Enable LPC snoop channel at requested port */ ++ /* Enable snoop channel at requested port */ + switch (channel) { + case 0: + snp_enable_reg_en = snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en; +@@ -216,23 +218,24 @@ static int phytium_lpc_enable_snoop(struct phytium_lpc_snoop *lpc_snoop, + return -EINVAL; + } + +- regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, snp_enable_reg_en, snp_enable_reg_en); +- regmap_update_bits(lpc_snoop->regmap, snp_addr_reg, snp_addr_reg_mask, +- lpc_port << snp_addr_reg_shift); ++ regmap_update_bits(snoop_ctrl->regmap, ++ snp_enable_reg, snp_enable_reg_en, snp_enable_reg_en); ++ regmap_update_bits(snoop_ctrl->regmap, snp_addr_reg, snp_addr_reg_mask, ++ snoop_port << snp_addr_reg_shift); + return rc; + } + +-static void phytium_lpc_disable_snoop(struct phytium_lpc_snoop *lpc_snoop, ++static void phytium_disable_snoop(struct phytium_snoop_ctrl *snoop_ctrl, + int channel) + { + switch (channel) { + case 0: +- regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, ++ regmap_update_bits(snoop_ctrl->regmap, snp_enable_reg, + snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en, + 0); + break; + case 1: +- regmap_update_bits(lpc_snoop->regmap, snp_enable_reg, ++ regmap_update_bits(snoop_ctrl->regmap, snp_enable_reg, + snp_enable_reg_snp2_en | snp_enable_reg_snp2_int_en, + 0); + break; +@@ -240,31 +243,31 @@ static void phytium_lpc_disable_snoop(struct phytium_lpc_snoop *lpc_snoop, + return; + } + +- kfifo_free(&lpc_snoop->chan[channel].fifo); +- misc_deregister(&lpc_snoop->chan[channel].miscdev); ++ kfifo_free(&snoop_ctrl->chan[channel].fifo); ++ misc_deregister(&snoop_ctrl->chan[channel].miscdev); + } + +-static int phytium_lpc_snoop_probe(struct platform_device *pdev) ++static int phytium_snoop_ctrl_probe(struct platform_device *pdev) + { +- struct phytium_lpc_snoop *lpc_snoop; ++ struct phytium_snoop_ctrl *snoop_ctrl; + struct device *dev; + u32 port; + int rc; + + dev = &pdev->dev; + +- lpc_snoop = devm_kzalloc(dev, sizeof(*lpc_snoop), GFP_KERNEL); +- if (!lpc_snoop) ++ snoop_ctrl = devm_kzalloc(dev, sizeof(*snoop_ctrl), GFP_KERNEL); ++ if (!snoop_ctrl) + return -ENOMEM; + +- lpc_snoop->regmap = syscon_node_to_regmap( +- pdev->dev.parent->of_node); +- if (IS_ERR(lpc_snoop->regmap)) { ++ snoop_ctrl->regmap = syscon_node_to_regmap( ++ pdev->dev.of_node); ++ if (IS_ERR(snoop_ctrl->regmap)) { + dev_err(dev, "Couldn't get regmap\n"); + return -ENODEV; + } + +- dev_set_drvdata(&pdev->dev, lpc_snoop); ++ dev_set_drvdata(&pdev->dev, snoop_ctrl); + + rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port); + if (rc) { +@@ -272,54 +275,55 @@ static int phytium_lpc_snoop_probe(struct platform_device *pdev) + return -ENODEV; + } + +- rc = phytium_lpc_snoop_config_irq(lpc_snoop, pdev); ++ rc = phytium_snoop_ctrl_config_irq(snoop_ctrl, pdev); + if (rc) + return rc; + +- rc = phytium_lpc_enable_snoop(lpc_snoop, dev, 0, port); ++ rc = phytium_enable_snoop(snoop_ctrl, dev, 0, port); + if (rc) + return rc; + + /* Configuration of 2nd snoop channel port is optional */ + if (of_property_read_u32_index(dev->of_node, "snoop-ports", + 1, &port) == 0) { +- rc = phytium_lpc_enable_snoop(lpc_snoop, dev, 1, port); ++ rc = phytium_enable_snoop(snoop_ctrl, dev, 1, port); + if (rc) +- phytium_lpc_disable_snoop(lpc_snoop, 0); ++ phytium_disable_snoop(snoop_ctrl, 0); + } + + return rc; + } + +-static int phytium_lpc_snoop_remove(struct platform_device *pdev) ++static int phytium_snoop_ctrl_remove(struct platform_device *pdev) + { +- struct phytium_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); ++ struct phytium_snoop_ctrl *snoop_ctrl = dev_get_drvdata(&pdev->dev); + + /* Disable both snoop channels */ +- phytium_lpc_disable_snoop(lpc_snoop, 0); +- phytium_lpc_disable_snoop(lpc_snoop, 1); ++ phytium_disable_snoop(snoop_ctrl, 0); ++ phytium_disable_snoop(snoop_ctrl, 1); + + return 0; + } + + +-static const struct of_device_id phytium_lpc_snoop_match[] = { +- { .compatible = "phytium,lpc-snoop"}, ++static const struct of_device_id phytium_snoop_ctrl_match[] = { ++ { .compatible = "phytium,snoop-ctrl"}, + { }, + }; + +-static struct platform_driver phytium_lpc_snoop_driver = { ++static struct platform_driver phytium_snoop_ctrl_driver = { + .driver = { + .name = DEVICE_NAME, +- .of_match_table = phytium_lpc_snoop_match, ++ .of_match_table = phytium_snoop_ctrl_match, + }, +- .probe = phytium_lpc_snoop_probe, +- .remove = phytium_lpc_snoop_remove, ++ .probe = phytium_snoop_ctrl_probe, ++ .remove = phytium_snoop_ctrl_remove, + }; + +-module_platform_driver(phytium_lpc_snoop_driver); ++module_platform_driver(phytium_snoop_ctrl_driver); + +-MODULE_DEVICE_TABLE(of, phytium_lpc_snoop_match); ++MODULE_DEVICE_TABLE(of, phytium_snoop_ctrl_match); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Lan Hengyu lanhengyu1395@phytium.com.cn"); +-MODULE_DESCRIPTION("Driver to control Phytium LPC snoop functionality"); ++MODULE_DESCRIPTION("Driver to control Phytium snoop controller functionality"); ++MODULE_VERSION(SNOOP_DRIVER_VERSION); +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 11eb84df78a5..2c8bbd7771b4 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -1136,3 +1136,13 @@ config MMC_PHYTIUM_MCI_PLTFM + If you have a controller with this interface, say Y or M here. + + If unsure, say N. ++ ++config MMC_PHYTIUM_MCI_PLTFM_V2 ++ tristate "Phytium V2 MultiMedia Card Interface support" ++ depends on ARCH_PHYTIUM && OF ++ default y if ARCH_PHYTIUM ++ help ++ This selects support for the V2 MultiMedia Card Interface on Phytium SoCs. ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index c373fad0ee58..561da7054ab7 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -115,3 +115,4 @@ obj-$(CONFIG_MMC_SDHCI_XENON) += sdhci-xenon-driver.o + sdhci-xenon-driver-y += sdhci-xenon.o sdhci-xenon-phy.o + + obj-$(CONFIG_MMC_PHYTIUM_MCI_PLTFM) += phytium-mci-plat.o phytium-mci.o ++obj-$(CONFIG_MMC_PHYTIUM_MCI_PLTFM_V2) += phytium-mci-plat-v2.o phytium-mci-v2.o +diff --git a/drivers/mmc/host/phytium-mci-plat-v2.c b/drivers/mmc/host/phytium-mci-plat-v2.c +new file mode 100644 +index 000000000000..afc5530474de +--- /dev/null ++++ b/drivers/mmc/host/phytium-mci-plat-v2.c +@@ -0,0 +1,256 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Phytium Multimedia Card Interface PCI driver ++ * ++ * Copyright (C) 2024 Phytium Technology Co.,Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "phytium-mci-v2.h" ++ ++static u32 mci_caps = MMC_CAP_CMD23; ++ ++static const struct dev_pm_ops phytium_mci_dev_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(phyt_mci_suspend, ++ phyt_mci_resume) ++ SET_RUNTIME_PM_OPS(phyt_mci_runtime_suspend, ++ phyt_mci_runtime_resume, NULL) ++}; ++ ++static ssize_t debug_enable_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ return sprintf(buf, "%d\n", host->debug_enable); ++} ++ ++static ssize_t debug_enable_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ int enable; ++ int ret; ++ ++ ret = sscanf(buf, "%d\n", &enable); ++ if (ret == 0) { ++ ret = -EINVAL; ++ return ret; ++ } ++ ++ host->debug_enable = enable; ++ ++ phytium_mci_set_debug_enable(host, host->debug_enable); ++ ++ return count; ++} ++ ++static ssize_t alive_enable_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ return sprintf(buf, "%d\n", host->alive_enable); ++} ++ ++static ssize_t alive_enable_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ int enable; ++ int ret; ++ ++ ret = sscanf(buf, "%d\n", &enable); ++ if (ret == 0) { ++ ret = -EINVAL; ++ return ret; ++ } ++ ++ host->alive_enable = enable; ++ ++ phytium_mci_set_alive_enable(host, host->alive_enable); ++ ++ return count; ++} ++ ++static DEVICE_ATTR_RW(debug_enable); ++static DEVICE_ATTR_RW(alive_enable); ++ ++static int phytium_mci_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct phytium_mci_host *host; ++ struct resource *res; ++ const struct acpi_device_id *match; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ mmc = mmc_alloc_host(sizeof(struct phytium_mci_host), &pdev->dev); ++ if (!mmc) ++ return -ENOMEM; ++ host = mmc_priv(mmc); ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto host_free; ++ ++ if (dev->of_node) { ++ host->src_clk = devm_clk_get(&pdev->dev, "phytium_mci_clk"); ++ if (IS_ERR(host->src_clk)) { ++ ret = PTR_ERR(host->src_clk); ++ goto host_free; ++ } ++ ++ host->clk_rate = clk_get_rate(host->src_clk); ++ } else if (has_acpi_companion(dev)) { ++ match = acpi_match_device(dev->driver->acpi_match_table, dev); ++ if (!match) { ++ dev_err(dev, "Error ACPI match data is missing\n"); ++ return -ENODEV; ++ } ++ host->clk_rate = 1200000000; ++ } ++ ++ host->is_use_dma = 1; ++ host->is_device_x100 = 0; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->regf_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->regf_base)) { ++ ret = PTR_ERR(host->regf_base); ++ goto host_free; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ host->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->base)) { ++ ret = PTR_ERR(host->base); ++ goto host_free; ++ } ++ ++ host->irq = platform_get_irq(pdev, 0); ++ ++ if (host->irq < 0) { ++ ret = -EINVAL; ++ goto host_free; ++ } ++ host->irq_flags = IRQF_SHARED; ++ dev_dbg(&pdev->dev, "%s %d:irq:%d\n", __func__, __LINE__, host->irq); ++ host->dev = &pdev->dev; ++ host->caps = mci_caps; ++ host->mmc = mmc; ++ ret = phyt_mci_common_probe(host); ++ if (ret == MCI_REALEASE_MEM) { ++ ret = -ENOMEM; ++ goto release_mem; ++ } else if (ret) { ++ goto release; ++ } ++ ++ ret = device_create_file(&mmc->class_dev, ++ &dev_attr_debug_enable); ++ if (ret < 0) ++ goto debug_enable_free; ++ ++ ret = device_create_file(&mmc->class_dev, ++ &dev_attr_alive_enable); ++ if (ret < 0) ++ goto alive_enable_free; ++ ++ platform_set_drvdata(pdev, mmc); ++ dev_info(&pdev->dev, "%s %d: probe phytium mci successful.\n", __func__, __LINE__); ++ return 0; ++ ++alive_enable_free: ++ device_remove_file(&mmc->class_dev, &dev_attr_alive_enable); ++debug_enable_free: ++ device_remove_file(&mmc->class_dev, &dev_attr_debug_enable); ++release: ++ phyt_mci_deinit_hw(host); ++release_mem: ++ if (host->dma.adma_table) { ++ dma_free_coherent(&pdev->dev, ++ MAX_BD_NUM * sizeof(struct phytium_adma2_64_desc), ++ host->dma.adma_table, host->dma.adma_addr); ++ } ++host_free: ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static int phytium_mci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct phytium_mci_host *host; ++ ++ mmc = platform_get_drvdata(pdev); ++ if (!mmc) { ++ dev_info(&pdev->dev, "%s %d: mmc is null.\n", __func__, __LINE__); ++ return -1; ++ } ++ host = mmc_priv(mmc); ++ if (!host) { ++ dev_info(&pdev->dev, "%s %d: host is null.\n", __func__, __LINE__); ++ mmc_remove_host(mmc); ++ mmc_free_host(mmc); ++ return -1; ++ } ++ del_timer(&host->alive_timer); ++ del_timer(&host->hotplug_timer); ++ mmc_remove_host(host->mmc); ++ ++ if (host->dma.adma_table) { ++ dma_free_coherent(&pdev->dev, ++ MAX_BD_NUM * sizeof(struct phytium_adma2_64_desc), ++ host->dma.adma_table, host->dma.adma_addr); ++ } ++ phyt_mci_deinit_hw(host); ++ mmc_free_host(mmc); ++ platform_set_drvdata(pdev, NULL); ++ return 0; ++} ++ ++static const struct of_device_id phytium_mci_of_ids[] = { ++ { .compatible = "phytium,mci_2.0", }, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, phytium_mci_of_ids); ++ ++#ifdef CONFIG_ACPI ++static const struct acpi_device_id phytium_mci_acpi_ids[] = { ++ { .id = "PHYT0061" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(acpi, phytium_mci_acpi_ids); ++#else ++#define phytium_mci_acpi_ids NULL ++#endif ++ ++static struct platform_driver phytium_mci_driver = { ++ .probe = phytium_mci_probe, ++ .remove = phytium_mci_remove, ++ .driver = { ++ .name = "phytium-mci-platform-2.0", ++ .of_match_table = phytium_mci_of_ids, ++ .acpi_match_table = phytium_mci_acpi_ids, ++ .pm = &phytium_mci_dev_pm_ops, ++ }, ++}; ++ ++module_platform_driver(phytium_mci_driver); ++ ++MODULE_DESCRIPTION("Phytium Multimedia Card Interface driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lai Xueyu "); ++MODULE_VERSION(PHYTIUM_MMC_V2_DRIVER_VERSION); +diff --git a/drivers/mmc/host/phytium-mci-plat.c b/drivers/mmc/host/phytium-mci-plat.c +index 7f0ef46dd9ea..43456031175e 100644 +--- a/drivers/mmc/host/phytium-mci-plat.c ++++ b/drivers/mmc/host/phytium-mci-plat.c +@@ -188,3 +188,4 @@ module_platform_driver(phytium_mci_driver); + MODULE_DESCRIPTION("Phytium Multimedia Card Interface driver"); + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Cheng Quan "); ++MODULE_VERSION(PHYTIUM_MMC_DRIVER_VERSION); +diff --git a/drivers/mmc/host/phytium-mci-v2.c b/drivers/mmc/host/phytium-mci-v2.c +new file mode 100644 +index 000000000000..248090682818 +--- /dev/null ++++ b/drivers/mmc/host/phytium-mci-v2.c +@@ -0,0 +1,1077 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Phytium Multimedia Card Interface ++ * ++ * Copyright (C) 2024 Phytium Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "phytium-mci-v2.h" ++ ++struct init_data_t *init_data; ++struct start_command_data_t *start_command_data; ++struct start_data_data_t *start_data_data; ++struct set_ios_data_t *set_ios_data; ++struct cmd_next_data_t *cmd_next_data; ++struct err_irq_data_t *err_irq_data; ++ ++static struct phytium_mci_host *shost; ++ ++static const u32 rv2ap_int_mask = MMC_RXRING_TAIL_INT_MASK; ++ ++static const u32 cmd_err_ints_mask = MCI_INT_MASK_RTO | MCI_INT_MASK_RCRC | MCI_INT_MASK_RE | ++ MCI_INT_MASK_DCRC | MCI_INT_MASK_DRTO | ++ MCI_MASKED_INTS_SBE_BCI; ++ ++static int ap_phytium_mci_cmd_next(struct phyt_msg_info *rxmsg); ++static int ap_phytium_mci_data_xfer_next(struct phyt_msg_info *rxmsg); ++static void phytium_mci_adma_reset(struct phytium_mci_host *host); ++static void phytium_mci_init(struct phytium_mci_host *host); ++static void phytium_mci_init_adma_table(struct phytium_mci_host *host, ++ struct phytium_mci_dma *dma); ++static void phytium_mci_init_hw(struct phytium_mci_host *host); ++static int phytium_mci_get_cd(struct mmc_host *mmc); ++static int phytium_mci_get_ro(struct mmc_host *mmc); ++static void phytium_mci_start_command(struct phytium_mci_host *host, ++ struct mmc_request *mrq, ++ struct mmc_command *cmd); ++static void ++phytium_mci_start_data(struct phytium_mci_host *host, struct mmc_request *mrq, ++ struct mmc_command *cmd, struct mmc_data *data); ++static void __phytium_mci_enable_sdio_irq(struct phytium_mci_host *host, int enable); ++static int phytium_check_msg(void); ++static int phytium_mci_card_busy(struct mmc_host *mmc); ++struct phyt_msg_info *shmem[RING_MAX]; ++struct phyt_msg_info *rvshmem[RING_MAX_RV]; ++ ++static void phytium_mci_set_int_mask(struct phytium_mci_host *host) ++{ ++ u32 int_mask; ++ ++ int_mask = ~rv2ap_int_mask; ++ ++ writel(int_mask, host->regf_base + MMC_RV2AP_INT_MASK); ++ dev_info(host->dev, "set int mask %x\n", int_mask); ++} ++ ++static void phytium_mci_prepare_data(struct phytium_mci_host *host, ++ struct mmc_request *mrq) ++{ ++ struct mmc_data *data = mrq->data; ++ ++ if (!(data->host_cookie & MCI_PREPARE_FLAG)) { ++ data->host_cookie |= MCI_PREPARE_FLAG; ++ data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, ++ mmc_get_dma_dir(data)); ++ } ++} ++ ++static void phytium_mci_unprepare_data(struct phytium_mci_host *host, ++ struct mmc_request *mrq) ++{ ++ struct mmc_data *data = mrq->data; ++ ++ if (data->host_cookie & MCI_ASYNC_FLAG) ++ return; ++ ++ if (data->host_cookie & MCI_PREPARE_FLAG) { ++ dma_unmap_sg(host->dev, data->sg, data->sg_len, mmc_get_dma_dir(data)); ++ data->host_cookie &= ~MCI_PREPARE_FLAG; ++ } ++} ++ ++static inline u32 ++phytium_mci_cmd_find_resp(struct phytium_mci_host *host, ++ struct mmc_request *mrq, ++ struct mmc_command *cmd) ++{ ++ u32 resp; ++ ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_R1: ++ case MMC_RSP_R1B: ++ resp = 0x5; ++ break; ++ ++ case MMC_RSP_R2: ++ resp = 0x7; ++ break; ++ ++ case MMC_RSP_R3: ++ resp = 0x1; ++ break; ++ ++ case MMC_RSP_NONE: ++ default: ++ resp = 0x0; ++ break; ++ } ++ ++ return resp; ++} ++ ++static inline ++u32 phytium_mci_cmd_prepare_raw_cmd(struct phytium_mci_host *host, ++ struct mmc_request *mrq, ++ struct mmc_command *cmd) ++{ ++ u32 opcode = cmd->opcode; ++ u32 resp = phytium_mci_cmd_find_resp(host, mrq, cmd); ++ u32 rawcmd = ((opcode & 0x3f) | ((resp & 0x7) << 6)); ++ ++ if (opcode == MMC_GO_INACTIVE_STATE || ++ (opcode == SD_IO_RW_DIRECT && ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) ++ rawcmd |= (0x1 << 14); ++ else if (opcode == SD_SWITCH_VOLTAGE) ++ rawcmd |= (0x1 << 28); ++ ++ if (test_and_clear_bit(MCI_CARD_NEED_INIT, &host->flags)) ++ rawcmd |= (0x1 << 15); ++ ++ if (cmd->data) { ++ struct mmc_data *data = cmd->data; ++ ++ rawcmd |= (0x1 << 9); ++ ++ if (data->flags & MMC_DATA_WRITE) ++ rawcmd |= (0x1 << 10); ++ } ++ ++ if (host->use_hold) ++ rawcmd |= (0x1 << 29); ++ ++ return (rawcmd | (0x1 << 31)); ++} ++ ++static inline void ++phytium_mci_adma_write_desc(struct phytium_mci_host *host, ++ struct phytium_adma2_64_desc *desc, ++ dma_addr_t addr, u32 len, u32 attribute) ++{ ++ desc->attribute = attribute; ++ desc->len = len; ++ desc->addr_lo = lower_32_bits(addr); ++ desc->addr_hi = upper_32_bits(addr); ++ dev_dbg(host->dev, "%s %d:addr_lo:0x%x ddr_hi:0x%x\n", __func__, ++ __LINE__, desc->addr_lo, desc->addr_hi); ++ ++ if ((attribute == 0x80000004) || (attribute == 0x8000000c)) { ++ desc->desc_lo = 0; ++ desc->desc_hi = 0; ++ } ++} ++ ++static void ++phytium_mci_data_sg_write_2_admc_table(struct phytium_mci_host *host, struct mmc_data *data) ++{ ++ struct phytium_adma2_64_desc *desc; ++ u32 dma_len, i; ++ dma_addr_t dma_address; ++ struct scatterlist *sg; ++ ++ phytium_mci_init_adma_table(host, &host->dma); ++ ++ desc = host->dma.adma_table; ++ for_each_sg(data->sg, sg, data->sg_count, i) { ++ dma_address = sg_dma_address(sg); ++ dma_len = sg_dma_len(sg); ++ ++ if (i == 0) { ++ if (sg_is_last(sg) || (data->sg_count == 1 && dma_len == SD_BLOCK_SIZE)) ++ phytium_mci_adma_write_desc(host, desc, dma_address, ++ dma_len, 0x8000000c); ++ else ++ phytium_mci_adma_write_desc(host, desc, dma_address, ++ dma_len, 0x8000001a); ++ } else if (sg_is_last(sg)) { ++ phytium_mci_adma_write_desc(host, desc, dma_address, ++ dma_len, 0x80000004); ++ } else { ++ phytium_mci_adma_write_desc(host, desc, dma_address, ++ dma_len, 0x80000012); ++ } ++ ++ desc++; ++ } ++} ++ ++static void phytium_mci_track_cmd_data(struct phytium_mci_host *host, ++ struct mmc_command *cmd, ++ struct mmc_data *data) ++{ ++ if (host->error) ++ dev_dbg(host->dev, "%s: cmd=%d arg=%08X; host->error=0x%08X\n", ++ __func__, cmd->opcode, cmd->arg, host->error); ++} ++ ++static void phytium_mci_request_done(struct phytium_mci_host *host, struct mmc_request *mrq) ++{ ++ phytium_mci_track_cmd_data(host, mrq->cmd, mrq->data); ++ ++ if (mrq->data) ++ phytium_mci_unprepare_data(host, mrq); ++ ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void phytium_mci_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ host->error = 0; ++ host->mrq = NULL; ++ WARN_ON(host->mrq); ++ host->mrq = mrq; ++ ++ dev_dbg(host->dev, "%s %d: cmd:%d arg:0x%x\n", __func__, __LINE__, ++ mrq->cmd->opcode, mrq->cmd->arg); ++ ++ if (mrq->sbc) { ++ phytium_mci_start_command(host, mrq, mrq->sbc); ++ return; ++ } ++ if (mrq->data) { ++ phytium_mci_prepare_data(host, mrq); ++ ++ if ((mrq->data->sg->length >= 512) && host->is_use_dma && ++ ((mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) || ++ (mrq->cmd->opcode == MMC_READ_SINGLE_BLOCK) || ++ (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) || ++ (mrq->cmd->opcode == MMC_WRITE_BLOCK) || ++ (mrq->cmd->opcode == SD_IO_RW_EXTENDED))) ++ ++ host->adtc_type = BLOCK_RW_ADTC; ++ else ++ host->adtc_type = COMMOM_ADTC; ++ ++ phytium_mci_start_data(host, mrq, mrq->cmd, mrq->data); ++ return; ++ } ++ phytium_mci_start_command(host, mrq, mrq->cmd); ++} ++ ++static void phytium_mci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; ++ ++ if (!data) ++ return; ++ ++ phytium_mci_prepare_data(host, mrq); ++ data->host_cookie |= MCI_ASYNC_FLAG; ++} ++ ++static void phytium_mci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, ++ int err) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; ++ ++ if (!data) ++ return; ++ ++ if (data->host_cookie & MCI_ASYNC_FLAG) { ++ data->host_cookie &= ~MCI_ASYNC_FLAG; ++ phytium_mci_unprepare_data(host, mrq); ++ } ++} ++ ++static void phytium_mci_data_read_without_dma(struct phytium_mci_host *host, ++ struct mmc_data *data) ++{ ++ u32 length, i, data_val, dma_len, tmp = 0; ++ u32 *virt_addr; ++ unsigned long flags; ++ struct scatterlist *sg; ++ ++ length = data->blocks * data->blksz; ++ ++ if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { ++ spin_lock_irqsave(&host->lock, flags); ++ if (data->host_cookie & MCI_ASYNC_FLAG) { ++ tmp = MCI_ASYNC_FLAG; ++ phytium_mci_post_req(host->mmc, data->mrq, 0); ++ } else { ++ phytium_mci_unprepare_data(host, data->mrq); ++ } ++ ++ for_each_sg(data->sg, sg, data->sg_count, i) { ++ dma_len = sg_dma_len(sg); ++ virt_addr = sg_virt(data->sg); ++ ++ for (i = 0; i < (dma_len / 4); i++) { ++ data_val = readl(host->regf_base + MCI_DATA); ++ memcpy(virt_addr, &data_val, 4); ++ ++virt_addr; ++ } ++ } ++ ++ if (tmp & MCI_ASYNC_FLAG) ++ phytium_mci_pre_req(host->mmc, data->mrq); ++ else ++ phytium_mci_prepare_data(host, data->mrq); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ } ++ data->bytes_xfered = length; ++} ++ ++static irqreturn_t phytium_mci_irq(int irq, void *dev_id) ++{ ++ struct phytium_mci_host *host = (struct phytium_mci_host *) dev_id; ++ u32 rv2ap_event; ++ ++ rv2ap_event = readl(host->regf_base + MMC_RV2AP_INT); ++ if (rv2ap_event & MMC_TXRING_HEAD_INT) { ++ rv2ap_event &= ~MMC_TXRING_HEAD_INT; ++ pr_debug("MCIAP %s MMC_TXRING_HEAD_INT %x\n", __func__, rv2ap_event); ++ writel(rv2ap_event, host->regf_base + MMC_RV2AP_INT); ++ } ++ if (rv2ap_event & MMC_RXRING_TAIL_INT) { ++ rv2ap_event &= ~MMC_RXRING_TAIL_INT; ++ pr_debug("MCIAP %s MMC_RXRING_TAIL_INT %x\n", __func__, rv2ap_event); ++ writel(rv2ap_event, host->regf_base + MMC_RV2AP_INT); ++ phytium_check_msg(); ++ } ++ return IRQ_HANDLED; ++} ++ ++static void phytium_mci_init_adma_table(struct phytium_mci_host *host, ++ struct phytium_mci_dma *dma) ++{ ++ struct phytium_adma2_64_desc *adma_table = dma->adma_table; ++ dma_addr_t dma_addr; ++ int i; ++ ++ memset(adma_table, 0, sizeof(struct phytium_adma2_64_desc) * MAX_BD_NUM); ++ ++ for (i = 0; i < (MAX_BD_NUM - 1); i++) { ++ dma_addr = dma->adma_addr + sizeof(*adma_table) * (i + 1); ++ adma_table[i].desc_lo = lower_32_bits(dma_addr); ++ adma_table[i].desc_hi = upper_32_bits(dma_addr); ++ adma_table[i].attribute = 0; ++ adma_table[i].NON1 = 0; ++ adma_table[i].len = 0; ++ adma_table[i].NON2 = 0; ++ } ++ ++ phytium_mci_adma_reset(host); ++} ++ ++static void phytium_mci_ack_sdio_irq(struct mmc_host *mmc) ++{ ++ unsigned long flags; ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ __phytium_mci_enable_sdio_irq(host, 1); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++int phyt_mci_suspend(struct device *dev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ phyt_mci_deinit_hw(host); ++ return 0; ++} ++EXPORT_SYMBOL(phyt_mci_suspend); ++ ++int phyt_mci_resume(struct device *dev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ phytium_mci_set_int_mask(host); ++ phytium_mci_init(host); ++ phytium_mci_init_hw(host); ++ return 0; ++} ++EXPORT_SYMBOL(phyt_mci_resume); ++ ++#endif ++ ++#ifdef CONFIG_PM ++int phyt_mci_runtime_suspend(struct device *dev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ phyt_mci_deinit_hw(host); ++ return 0; ++} ++EXPORT_SYMBOL(phyt_mci_runtime_suspend); ++ ++int phyt_mci_runtime_resume(struct device *dev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(dev); ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ phytium_mci_set_int_mask(host); ++ phytium_mci_init(host); ++ phytium_mci_init_hw(host); ++ return 0; ++} ++EXPORT_SYMBOL(phyt_mci_runtime_resume); ++ ++#endif ++ ++static int phytium_ap_to_rv(struct phyt_msg_info *msg) ++{ ++ int i; ++ int ret = 0; ++ int tx_t, tx_h, p; ++ ++ tx_t = readl(shost->regf_base + MMC_TX_TAIL) & 0xffff; ++ tx_h = readl(shost->regf_base + MMC_TX_HEAD) & 0xffff; ++ ++ if ((tx_t + 1) % RING_MAX == tx_h) { ++ pr_err("mci ring buff full\n"); ++ return -1; ++ } ++ ++ p = tx_t; ++ ++ tx_t = (tx_t + 1) % RING_MAX; ++ ++ shmem[p] = (struct phyt_msg_info *)(*shmem + p); ++ pr_debug("MCIAP shmem[%d] %x\n", p, (unsigned int)(long)shmem[p]); ++ pr_debug("MCIAP MSG CMD:%d SCMD:%d\n", msg->cmd_type, msg->cmd_subid); ++ ++ /*write msg to shmem*/ ++ memcpy(shmem[p], msg, sizeof(struct phyt_msg_info)); ++ ++ /*update tx tail pointer*/ ++ writel(tx_t | MMC_TX_TAIL_INT, shost->regf_base + MMC_TX_TAIL); ++ ++ /*wait and check status*/ ++ for (i = 0; i < COMPLETE_TIMEOUT; i++) { ++ dsb(sy); ++ if (shmem[p]->status0 == GOING || shmem[p]->status0 == NOT_READY) { ++ pr_debug("MCIAP [%d] not complete %x\r\n", p, shmem[p]->status0); ++ } else if (shmem[p]->status0 == SUCCESS) { ++ ret = shmem[p]->status1; ++ pr_debug("MCIAP [%d] complete and return %d\r\n", p, ret); ++ /*clear status*/ ++ shmem[p]->status0 = 0; ++ shmem[p]->status1 = 0; ++ break; ++ } else if (shmem[p]->status0 >= GENERIC_ERROR) { ++ pr_debug("MCIAP [%d] status error %x\r\n", p, shmem[p]->status0); ++ ret = -1; ++ /*clear status*/ ++ shmem[p]->status0 = 0; ++ shmem[p]->status1 = 0; ++ break; ++ } ++ udelay(40); ++ } ++ pr_debug("MCIAP %s end [%d] times:%d\n", __func__, p, i); ++ return ret; ++} ++ ++static void phytium_mci_init(struct phytium_mci_host *host) ++{ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_INIT; ++ ++ pr_debug("MCIAP host->mmc->caps %x host->clk_rate %ld\n", ++ host->mmc->caps, host->clk_rate); ++ ++ init_data = (struct init_data_t *)host->msg.data; ++ init_data->caps = host->mmc->caps; ++ init_data->clk_rate = host->clk_rate; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static void phytium_mci_init_hw(struct phytium_mci_host *host) ++{ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_INIT_HW; ++ ++ phytium_ap_to_rv(&host->msg); ++ dev_info(host->dev, "init hardware done!"); ++} ++ ++void phyt_mci_deinit_hw(struct phytium_mci_host *host) ++{ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_DEINIT_HW; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++EXPORT_SYMBOL_GPL(phyt_mci_deinit_hw); ++ ++static void phytium_mci_start_command(struct phytium_mci_host *host, ++ struct mmc_request *mrq, ++ struct mmc_command *cmd) ++{ ++ u32 rawcmd; ++ ++ host->cmd = cmd; ++ host->mrq = mrq; ++ rawcmd = phytium_mci_cmd_prepare_raw_cmd(host, mrq, cmd); ++ ++ pr_debug("MCIAP arg%x flags%x opcode%d rawcmd%x\n", ++ host->cmd->arg, host->cmd->flags, host->cmd->opcode, rawcmd); ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_START_CMD; ++ ++ start_command_data = (struct start_command_data_t *)host->msg.data; ++ start_command_data->cmd_arg = cmd->arg; ++ start_command_data->cmd_flags = cmd->flags; ++ start_command_data->cmd_opcode = cmd->opcode; ++ start_command_data->rawcmd = rawcmd; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static void ++phytium_mci_start_data(struct phytium_mci_host *host, struct mmc_request *mrq, ++ struct mmc_command *cmd, struct mmc_data *data) ++{ ++ u32 rawcmd; ++ ++ host->cmd = cmd; ++ cmd->error = 0; ++ host->mrq = mrq; ++ host->data = data; ++ rawcmd = phytium_mci_cmd_prepare_raw_cmd(host, mrq, cmd); ++ phytium_mci_data_sg_write_2_admc_table(host, data); ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_START_DATA; ++ ++ start_data_data = (struct start_data_data_t *)host->msg.data; ++ start_data_data->data_flags = data->flags; ++ start_data_data->adtc_type = host->adtc_type; ++ start_data_data->adma_addr = host->dma.adma_addr; ++ start_data_data->mrq_data_blksz = mrq->data->blksz; ++ start_data_data->mrq_data_blocks = mrq->data->blocks; ++ start_data_data->cmd_arg = cmd->arg; ++ start_data_data->rawcmd = rawcmd; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static void phytium_mci_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_OPS_SET_IOS; ++ ++ set_ios_data = (struct set_ios_data_t *)host->msg.data; ++ set_ios_data->ios_clock = ios->clock; ++ set_ios_data->ios_timing = ios->timing; ++ set_ios_data->ios_bus_width = ios->bus_width; ++ set_ios_data->ios_power_mode = ios->power_mode; ++ ++ phytium_ap_to_rv(&host->msg); ++ ++ if (ios->power_mode == MMC_POWER_UP) ++ set_bit(MCI_CARD_NEED_INIT, &host->flags); ++} ++ ++static void __phytium_mci_enable_sdio_irq(struct phytium_mci_host *host, int enable) ++{ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_SDIO_IRQ_EN; ++ ++ host->msg.data[0] = enable & 0xFF; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static void phytium_mci_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ __phytium_mci_enable_sdio_irq(host, enable); ++} ++ ++static int phytium_mci_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ int ret = 0; ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_SET; ++ host->msg.cmd_subid = MCI_OPS_SWITCH_VOLT; ++ ++ host->msg.data[0] = ios->signal_voltage & 0xFF; ++ ++ ret = phytium_ap_to_rv(&host->msg); ++ ++ pr_debug("MCIAP %s %d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static void phytium_mci_hw_reset(struct mmc_host *mmc) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_DEFAULT; ++ host->msg.cmd_subid = MCI_HW_RESET; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static void phytium_mci_adma_reset(struct phytium_mci_host *host) ++{ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_DEFAULT; ++ host->msg.cmd_subid = MCI_ADMA_RESET; ++ ++ phytium_ap_to_rv(&host->msg); ++} ++ ++static int phytium_mci_get_cd(struct mmc_host *mmc) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ u32 status; ++ ++ if (mmc->caps & MMC_CAP_NONREMOVABLE) ++ return 1; ++ ++ status = readl(host->regf_base + MCI_CARD_DETECT); ++ ++ pr_debug("MCIAP get cd %d\n", status); ++ ++ if ((status & 0x1) == 0x1) ++ return 0; ++ ++ return 1; ++} ++ ++static int phytium_mci_card_busy(struct mmc_host *mmc) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ int ret; ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_GET; ++ host->msg.cmd_subid = MCI_GET_CARD_BUSY; ++ ++ ret = phytium_ap_to_rv(&host->msg); ++ ++ pr_debug("MCIAP card busy %d\n", ret); ++ return ret; ++} ++ ++static int phytium_mci_get_ro(struct mmc_host *mmc) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ int ret; ++ ++ host->msg.cmd_type = PHYTMMC_MSG_CMD_GET; ++ host->msg.cmd_subid = MCI_GET_RO; ++ ++ ret = phytium_ap_to_rv(&host->msg); ++ ++ dev_dbg(host->dev, "MCIAP ro %d\n", ret); ++ ++ return ret; ++} ++ ++static int ap_phytium_mci_cmd_next(struct phyt_msg_info *rxmsg) ++{ ++ struct phytium_mci_host *host; ++ u32 events; ++ ++ host = shost; ++ ++ if (!host->cmd) ++ return 1; ++ ++ cmd_next_data = (struct cmd_next_data_t *)rxmsg->data; ++ events = cmd_next_data->events; ++ host->cmd->resp[0] = cmd_next_data->response0; ++ host->cmd->resp[1] = cmd_next_data->response1; ++ host->cmd->resp[2] = cmd_next_data->response2; ++ host->cmd->resp[3] = cmd_next_data->response3; ++ ++ if (!(events & (MCI_RAW_INTS_CMD | MCI_INT_MASK_HTO))) { ++ if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) && (events & MCI_RAW_INTS_RTO) ++ && readl(host->regf_base + MCI_CARD_DETECT)) { ++ host->cmd->error = -ENOMEDIUM; ++ host->cmd->resp[0] = 0; ++ } else if (events & MCI_RAW_INTS_RTO || ++ (host->cmd->opcode != MMC_SEND_TUNING_BLOCK && ++ host->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)) { ++ host->cmd->error = -ETIMEDOUT; ++ } else if (events & MCI_RAW_INTS_RCRC) { ++ host->cmd->error = -EILSEQ; ++ } else { ++ host->cmd->error = -ETIMEDOUT; ++ } ++ } ++ ++ if ((host->cmd->error && !(host->cmd->opcode == MMC_SEND_TUNING_BLOCK || ++ host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)) || ++ (host->mrq->sbc && host->mrq->sbc->error)) { ++ phytium_mci_request_done(host, host->mrq); ++ } else if (host->cmd == host->mrq->sbc) { ++ if ((host->mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) || ++ (host->mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) || ++ (host->mrq->cmd->opcode == MMC_READ_SINGLE_BLOCK) || ++ (host->mrq->cmd->opcode == MMC_WRITE_BLOCK)) { ++ dev_dbg(host->dev, "%s %d:sbc done and next cmd :%d length:%d\n", ++ __func__, __LINE__, host->mrq->cmd->opcode, ++ host->mrq->data->sg->length); ++ phytium_mci_prepare_data(host, host->mrq); ++ if (host->is_use_dma) ++ host->adtc_type = BLOCK_RW_ADTC; ++ else ++ host->adtc_type = COMMOM_ADTC; ++ phytium_mci_start_data(host, host->mrq, host->mrq->cmd, host->mrq->data); ++ } else { ++ dev_err(host->dev, "%s %d:ERROR: cmd %d followers the SBC\n", ++ __func__, __LINE__, host->cmd->opcode); ++ } ++ } else if (!host->cmd->data) { ++ phytium_mci_request_done(host, host->mrq); ++ } ++ return 1; ++} ++ ++static int ap_phytium_mci_data_xfer_next(struct phyt_msg_info *rxmsg) ++{ ++ struct phytium_mci_host *host; ++ u32 events; ++ struct mmc_request *mrq; ++ struct mmc_data *data; ++ ++ host = shost; ++ mrq = host->mrq; ++ data = host->data; ++ ++ events = ((uint32_t *)(rxmsg->data))[0]; ++ ++ if (events & MCI_RAW_INTS_DTO) { ++ if (host->adtc_type == COMMOM_ADTC && ++ (mrq->cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) ++ phytium_mci_data_read_without_dma(host, data); ++ else ++ data->bytes_xfered = data->blocks * data->blksz; ++ } else { ++ data->bytes_xfered = 0; ++ if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ && readl(host->regf_base + MCI_CARD_DETECT) ++ && (events & cmd_err_ints_mask)) { ++ data->error = -ENOMEDIUM; ++ data->mrq->cmd->error = -ENOMEDIUM; ++ } else if (events & (MCI_RAW_INTS_DCRC | MCI_RAW_INTS_EBE | ++ MCI_RAW_INTS_SBE_BCI)) { ++ data->error = -EILSEQ; ++ } else { ++ data->error = -ETIMEDOUT; ++ } ++ } ++ ++ if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && ++ (data->error || !mrq->sbc)) { ++ phytium_mci_start_command(host, mrq, mrq->stop); ++ } else { ++ phytium_mci_request_done(host, mrq); ++ } ++ return 1; ++} ++ ++static int ap_phytium_mci_card_detect_irq(struct phyt_msg_info *rxmsg) ++{ ++ u8 cd; ++ struct phytium_mci_host *host; ++ ++ host = shost; ++ cd = rxmsg->data[0]; ++ ++ pr_debug("MCIAP card_detect_irq %d\n", cd); ++ if (cd) { ++ if (host->mmc->card) { ++ cancel_delayed_work(&host->mmc->detect); ++ mmc_detect_change(host->mmc, msecs_to_jiffies(0)); ++ } ++ } else { ++ cancel_delayed_work(&host->mmc->detect); ++ mmc_detect_change(host->mmc, msecs_to_jiffies(200)); ++ } ++ return 1; ++} ++ ++static int ap_phytium_mci_err_irq(struct phyt_msg_info *rxmsg) ++{ ++ u32 raw_ints; ++ u32 dmac_status; ++ u32 ints_mask; ++ u32 dmac_mask; ++ u32 opcode; ++ ++ err_irq_data = (struct err_irq_data_t *)rxmsg->data; ++ raw_ints = err_irq_data->raw_ints; ++ ints_mask = err_irq_data->ints_mask; ++ dmac_status = err_irq_data->dmac_status; ++ dmac_mask = err_irq_data->dmac_mask; ++ opcode = err_irq_data->opcode; ++ ++ pr_err("MCIAP ERR raw_ints:%x ints_mask:%x dmac_status:%x dmac_mask:%x cmd:%d\n", ++ raw_ints, ints_mask, dmac_status, dmac_mask, opcode); ++ ++ return 1; ++} ++ ++static int phytium_check_msg(void) ++{ ++ int rx_t, rx_h; ++ int complete; ++ struct phyt_msg_info rxmsg; ++ int p = 0; ++ ++ rx_t = readl(shost->regf_base + MMC_RX_TAIL) & 0xffff; ++ rx_h = readl(shost->regf_base + MMC_RX_HEAD) & 0xffff; ++ ++ while (rx_t != rx_h) { ++ pr_debug("MCIAP %s rx_t:%d rx_h:%d\n", __func__, rx_t, rx_h); ++ ++ p = rx_h; ++ rx_h = (rx_h + 1) % RING_MAX_RV; ++ ++ writel(rx_h, shost->regf_base + MMC_RX_HEAD); ++ rvshmem[p] = (struct phyt_msg_info *)(*rvshmem + p); ++ pr_debug("MCIAP %s %d %x\n", __func__, p, (unsigned int)(long)rvshmem[p]); ++ ++ /*read msg from shmem*/ ++ memcpy(&rxmsg, rvshmem[p], sizeof(struct phyt_msg_info)); ++ /*read msg from shmem*/ ++ ++ /*execute cmd*/ ++ switch (rxmsg.cmd_type) { ++ case PHYTMMC_MSG_CMD_REPORT: ++ switch (rxmsg.cmd_subid) { ++ case MCI_CMD_NEXT: ++ complete = ap_phytium_mci_cmd_next(&rxmsg); ++ break; ++ case MCI_DATA_NEXT: ++ complete = ap_phytium_mci_data_xfer_next(&rxmsg); ++ break; ++ case MCI_CD_IRQ: ++ complete = ap_phytium_mci_card_detect_irq(&rxmsg); ++ break; ++ case MCI_ERR_IRQ: ++ complete = ap_phytium_mci_err_irq(&rxmsg); ++ break; ++ default: ++ pr_debug("MCIAP invalid sub cmd\r\n"); ++ break; ++ } ++ break; ++ default: ++ pr_debug("MCIAP invalid cmd\r\n"); ++ break; ++ } ++ ++ /*write complete*/ ++ rvshmem[p]->status0 = complete; ++ } ++ return 1; ++} ++ ++int phytium_mci_set_debug_enable(struct phytium_mci_host *host, bool enable) ++{ ++ static bool debug_enable; ++ u32 debug_reg; ++ ++ if (enable == debug_enable) ++ return 0; ++ ++ debug_enable = enable; ++ ++ debug_reg = readl(host->regf_base + MCI_DEBUG); ++ pr_debug("MCIAP %s debug_reg %x\n", __func__, debug_reg); ++ ++ if (!debug_enable && (debug_reg & MCI_DEBUG_ENABLE)) { ++ debug_reg &= ~MCI_DEBUG_ENABLE; ++ writel(debug_reg, host->regf_base + MCI_DEBUG); ++ } else if (debug_enable && !(debug_reg & MCI_DEBUG_ENABLE)) { ++ debug_reg |= MCI_DEBUG_ENABLE; ++ writel(debug_reg, host->regf_base + MCI_DEBUG); ++ } ++ ++ return 1; ++} ++EXPORT_SYMBOL(phytium_mci_set_debug_enable); ++ ++int phytium_mci_set_alive_enable(struct phytium_mci_host *host, bool enable) ++{ ++ static bool alive_enable; ++ u32 debug_reg; ++ ++ if (enable == alive_enable) ++ return 0; ++ ++ alive_enable = enable; ++ ++ debug_reg = readl(host->regf_base + MCI_DEBUG); ++ pr_debug("MCIAP %s debug_reg %x\n", __func__, debug_reg); ++ ++ if (!alive_enable && (debug_reg & MCI_ALIVE_ENABLE)) { ++ debug_reg &= ~MCI_ALIVE_ENABLE; ++ writel(debug_reg, host->regf_base + MCI_DEBUG); ++ del_timer(&host->alive_timer); ++ } else if (alive_enable && !(debug_reg & MCI_ALIVE_ENABLE)) { ++ debug_reg |= MCI_ALIVE_ENABLE | MCI_ALIVE; ++ writel(debug_reg, host->regf_base + MCI_DEBUG); ++ add_timer(&host->alive_timer); ++ } ++ ++ return 1; ++} ++EXPORT_SYMBOL(phytium_mci_set_alive_enable); ++ ++static void alive_timer_func(struct timer_list *t) ++{ ++ struct phytium_mci_host *host; ++ u32 debug_reg; ++ ++ host = from_timer(host, t, alive_timer); ++ if (!host) ++ return; ++ ++ debug_reg = readl(host->regf_base + MCI_DEBUG); ++ pr_debug("MCIAP %s debug_reg %x\n", __func__, debug_reg); ++ debug_reg |= MCI_ALIVE; ++ writel(debug_reg, host->regf_base + MCI_DEBUG); ++ mod_timer(&host->alive_timer, jiffies + msecs_to_jiffies(5000)); ++} ++ ++static struct mmc_host_ops phytium_mci_ops = { ++ .post_req = phytium_mci_post_req, ++ .pre_req = phytium_mci_pre_req, ++ .request = phytium_mci_ops_request, ++ .set_ios = phytium_mci_ops_set_ios, ++ .get_cd = phytium_mci_get_cd, ++ .get_ro = phytium_mci_get_ro, ++ .enable_sdio_irq = phytium_mci_enable_sdio_irq, ++ .ack_sdio_irq = phytium_mci_ack_sdio_irq, ++ .card_busy = phytium_mci_card_busy, ++ .start_signal_voltage_switch = phytium_mci_ops_switch_volt, ++ .hw_reset = phytium_mci_hw_reset, ++}; ++ ++int phyt_mci_common_probe(struct phytium_mci_host *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ struct device *dev = host->dev; ++ int ret; ++ ++ shost = host; ++ ++ dev_info(host->dev, "phytium_mci_common_probe start\n"); ++ ++ *shmem = host->base; ++ *rvshmem = (struct phyt_msg_info *)(*shmem + RING_MAX); ++ ++ dma_set_mask(dev, DMA_BIT_MASK(64)); ++ dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); ++ ++ host->alive_timer.expires = jiffies + msecs_to_jiffies(5000); ++ timer_setup(&host->alive_timer, alive_timer_func, 0); ++ ++ mmc->f_min = MCI_F_MIN; ++ if (!mmc->f_max) ++ mmc->f_max = MCI_F_MAX; ++ ++ mmc->ops = &phytium_mci_ops; ++ mmc->ocr_avail_sdio = MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->ocr_avail_sd = MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->ocr_avail_mmc = MMC_VDD_165_195; ++ mmc->ocr_avail = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->caps |= host->caps; ++ ++ if (mmc->caps & MMC_CAP_SDIO_IRQ) { ++ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; ++ dev_dbg(host->dev, "%s %d: MMC_CAP_SDIO_IRQ\n", __func__, __LINE__); ++ } ++ mmc->caps2 |= host->caps2; ++ ++ phytium_mci_set_int_mask(host); ++ ++ phytium_mci_init(host); ++ ++ phytium_mci_init_hw(host); ++ ++ if (host->is_use_dma) { ++ /* MMC core transfer sizes tunable parameters */ ++ mmc->max_segs = MAX_BD_NUM; ++ mmc->max_seg_size = 4 * 1024; ++ mmc->max_blk_size = 512; ++ mmc->max_req_size = 512 * 1024; ++ mmc->max_blk_count = mmc->max_req_size / 512; ++ host->dma.adma_table = dma_alloc_coherent(host->dev, ++ MAX_BD_NUM * ++ sizeof(struct phytium_adma2_64_desc), ++ &host->dma.adma_addr, GFP_KERNEL); ++ if (!host->dma.adma_table) ++ return MCI_REALEASE_MEM; ++ ++ host->dma.desc_sz = ADMA2_64_DESC_SZ; ++ phytium_mci_init_adma_table(host, &host->dma); ++ } else { ++ mmc->max_segs = MAX_BD_NUM; ++ mmc->max_seg_size = 4 * 1024; ++ mmc->max_blk_size = 512; ++ mmc->max_req_size = 4 * 512; ++ mmc->max_blk_count = mmc->max_req_size / 512; ++ } ++ ++ spin_lock_init(&host->lock); ++ ++ ret = devm_request_irq(host->dev, host->irq, phytium_mci_irq, ++ host->irq_flags, "phytium-mci", host); ++ if (ret) ++ return ret; ++ ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ dev_err(host->dev, "%s %d: mmc add host!\n", __func__, __LINE__); ++ return ret; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(phyt_mci_common_probe); ++ ++MODULE_DESCRIPTION("Phytium Multimedia Card Interface driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lai Xueyu "); ++MODULE_VERSION(PHYTIUM_MMC_V2_DRIVER_VERSION); +diff --git a/drivers/mmc/host/phytium-mci-v2.h b/drivers/mmc/host/phytium-mci-v2.h +new file mode 100644 +index 000000000000..f02f9db33133 +--- /dev/null ++++ b/drivers/mmc/host/phytium-mci-v2.h +@@ -0,0 +1,314 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Driver for Phytium Multimedia Card Interface ++ * ++ * Copyright (C) 2024 Phytium Technology Co., Ltd. ++ */ ++ ++#ifndef __PHYTIUM_MCI_H ++#define __PHYTIUM_MCI_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*------------------------------------------------------*/ ++/* Common Definition */ ++/*------------------------------------------------------*/ ++#define PHYTIUM_MMC_V2_DRIVER_VERSION "1.1.0" ++ ++#define SD_BLOCK_SIZE 512 ++#define MAX_BD_NUM 128 ++#define MCI_CLK 1200000000 ++#define MCI_REALEASE_MEM 0x1 ++ ++#define MCI_PREPARE_FLAG (0x1 << 0) ++#define MCI_ASYNC_FLAG (0x1 << 1) ++#define MCI_MMAP_FLAG (0x1 << 2) ++ ++#define MCI_F_MIN 400000 ++#define MCI_F_MAX 50000000 ++ ++/* MCI_RAW_INTS mask */ ++#define MCI_RAW_INTS_CD (0x1 << 0) /* W1C */ ++#define MCI_RAW_INTS_RE (0x1 << 1) /* W1C */ ++#define MCI_RAW_INTS_CMD (0x1 << 2) /* W1C */ ++#define MCI_RAW_INTS_DTO (0x1 << 3) /* W1C */ ++#define MCI_RAW_INTS_TXDR (0x1 << 4) /* W1C */ ++#define MCI_RAW_INTS_RXDR (0x1 << 5) /* W1C */ ++#define MCI_RAW_INTS_RCRC (0x1 << 6) /* W1C */ ++#define MCI_RAW_INTS_DCRC (0x1 << 7) /* W1C */ ++#define MCI_RAW_INTS_RTO (0x1 << 8) /* W1C */ ++#define MCI_RAW_INTS_DRTO (0x1 << 9) /* W1C */ ++#define MCI_RAW_INTS_HTO (0x1 << 10) /* W1C */ ++#define MCI_RAW_INTS_FRUN (0x1 << 11) /* W1C */ ++#define MCI_RAW_INTS_HLE (0x1 << 12) /* W1C */ ++#define MCI_RAW_INTS_SBE_BCI (0x1 << 13) /* W1C */ ++#define MCI_RAW_INTS_ACD (0x1 << 14) /* W1C */ ++#define MCI_RAW_INTS_EBE (0x1 << 15) /* W1C */ ++#define MCI_RAW_INTS_SDIO (0x1 << 16) /* W1C */ ++ ++/* MCI_MASKED_INTS mask */ ++#define MCI_MASKED_INTS_CD (0x1 << 0) /* RO */ ++#define MCI_MASKED_INTS_RE (0x1 << 1) /* RO */ ++#define MCI_MASKED_INTS_CMD (0x1 << 2) /* RO */ ++#define MCI_MASKED_INTS_DTO (0x1 << 3) /* RO */ ++#define MCI_MASKED_INTS_TXDR (0x1 << 4) /* RO */ ++#define MCI_MASKED_INTS_RXDR (0x1 << 5) /* RO */ ++#define MCI_MASKED_INTS_RCRC (0x1 << 6) /* RO */ ++#define MCI_MASKED_INTS_DCRC (0x1 << 7) /* RO */ ++#define MCI_MASKED_INTS_RTO (0x1 << 8) /* RO */ ++#define MCI_MASKED_INTS_DRTO (0x1 << 9) /* RO */ ++#define MCI_MASKED_INTS_HTO (0x1 << 10) /* RO */ ++#define MCI_MASKED_INTS_FRUN (0x1 << 11) /* RO */ ++#define MCI_MASKED_INTS_HLE (0x1 << 12) /* RO */ ++#define MCI_MASKED_INTS_SBE_BCI (0x1 << 13) /* RO */ ++#define MCI_MASKED_INTS_ACD (0x1 << 14) /* RO */ ++#define MCI_MASKED_INTS_EBE (0x1 << 15) /* RO */ ++#define MCI_MASKED_INTS_SDIO (0x1 << 16) /* RO */ ++ ++/* MCI_INT_MASK mask */ ++#define MCI_INT_MASK_CD (0x1 << 0) /* RW */ ++#define MCI_INT_MASK_RE (0x1 << 1) /* RW */ ++#define MCI_INT_MASK_CMD (0x1 << 2) /* RW */ ++#define MCI_INT_MASK_DTO (0x1 << 3) /* RW */ ++#define MCI_INT_MASK_TXDR (0x1 << 4) /* RW */ ++#define MCI_INT_MASK_RXDR (0x1 << 5) /* RW */ ++#define MCI_INT_MASK_RCRC (0x1 << 6) /* RW */ ++#define MCI_INT_MASK_DCRC (0x1 << 7) /* RW */ ++#define MCI_INT_MASK_RTO (0x1 << 8) /* RW */ ++#define MCI_INT_MASK_DRTO (0x1 << 9) /* RW */ ++#define MCI_INT_MASK_HTO (0x1 << 10) /* RW */ ++#define MCI_INT_MASK_FRUN (0x1 << 11) /* RW */ ++#define MCI_INT_MASK_HLE (0x1 << 12) /* RW */ ++#define MCI_INT_MASK_SBE_BCI (0x1 << 13) /* RW */ ++#define MCI_INT_MASK_ACD (0x1 << 14) /* RW */ ++#define MCI_INT_MASK_EBE (0x1 << 15) /* RW */ ++#define MCI_INT_MASK_SDIO (0x1 << 16) /* RW */ ++ ++#define MCI_CARD_DETECT 0x30 /* the card detect reg */ ++#define MCI_DATA 0x34 /* the data FIFO access */ ++ ++#define MCI_DEBUG 0x58 /* debug function */ ++ ++/* MCI_DEBUG mask */ ++#define MCI_DEBUG_ENABLE (0x1 << 0) /* RW */ ++#define MCI_ALIVE_ENABLE (0x1 << 1) /* RW */ ++#define MCI_ALIVE (0x1 << 2) /* RW */ ++#define MCI_HAVE_LOG (0x1 << 3) /* RW */ ++#define MCI_SIZE (0xf << 4) /* RW */ ++#define MCI_ADDR (0x3fffff << 8) /* RW */ ++ ++#define AP_TO_RV_MAX_DATA 64 ++#define MCI_HW_RESET 0x00 ++#define MCI_ADMA_RESET 0x01 ++#define MCI_INIT 0x00 ++#define MCI_INIT_HW 0x01 ++#define MCI_DEINIT_HW 0x02 ++#define MCI_START_CMD 0x03 ++#define MCI_START_DATA 0x04 ++#define MCI_OPS_SET_IOS 0x05 ++#define MCI_SDIO_IRQ_EN 0x06 ++#define MCI_OPS_SWITCH_VOLT 0x07 ++#define MCI_GET_CD 0x00 ++#define MCI_GET_CARD_BUSY 0x01 ++#define MCI_GET_STATUS 0x02 ++#define MCI_GET_RO 0x03 ++#define MCI_CD_IRQ 0x00 ++#define MCI_ERR_IRQ 0x01 ++#define MCI_CMD_NEXT 0x02 ++#define MCI_DATA_NEXT 0x03 ++ ++#define RING_MAX 20 ++#define RING_MAX_RV 10 ++ ++#define COMPLETE_TIMEOUT 200 ++ ++#define MMC_TX_HEAD 0x0 ++#define MMC_TX_TAIL 0x4 ++#define MMC_RX_HEAD 0x8 ++#define MMC_RX_TAIL 0xc ++#define MMC_TX_TAIL_INT (0x1 << 16) /* RW */ ++ ++#define MMC_RV2AP_INT_MASK 0x028 ++#define MMC_TXRING_HEAD_INT_MASK 0x1 /* RW */ ++#define MMC_RXRING_TAIL_INT_MASK (0x1 << 1) /* RW */ ++ ++#define MMC_RV2AP_INT 0x02c ++#define MMC_TXRING_HEAD_INT 0x1 /* RW */ ++#define MMC_RXRING_TAIL_INT (0x1 << 1) /* RW */ ++/*--------------------------------------*/ ++/* Structure Type */ ++/*--------------------------------------*/ ++/* Maximum segments assuming a 512KiB maximum requisition */ ++/* size and a minimum4KiB page size. */ ++#define MCI_MAX_SEGS 128 ++/* ADMA2 64-bit DMA descriptor size */ ++#define ADMA2_64_DESC_SZ 32 ++ ++/* Each descriptor can transfer up to 4KB of data in chained mode */ ++/*ADMA2 64-bit descriptor.*/ ++struct phytium_adma2_64_desc { ++ u32 attribute; ++#define IDMAC_DES0_DIC BIT(1) ++#define IDMAC_DES0_LD BIT(2) ++#define IDMAC_DES0_FD BIT(3) ++#define IDMAC_DES0_CH BIT(4) ++#define IDMAC_DES0_ER BIT(5) ++#define IDMAC_DES0_CES BIT(30) ++#define IDMAC_DES0_OWN BIT(31) ++ u32 NON1; ++ u32 len; ++ u32 NON2; ++ u32 addr_lo; /* Lower 32-bits of Buffer Address Pointer 1*/ ++ u32 addr_hi; /* Upper 32-bits of Buffer Address Pointer 1*/ ++ u32 desc_lo; /* Lower 32-bits of Next Descriptor Address */ ++ u32 desc_hi; /* Upper 32-bits of Next Descriptor Address */ ++} __packed __aligned(4); ++ ++struct phytium_mci_dma { ++ struct scatterlist *sg; /* I/O scatter list */ ++ /* ADMA descriptor table, pointer to adma_table array */ ++ struct phytium_adma2_64_desc *adma_table; ++ /* Mapped ADMA descr. table, the physical address of adma_table array */ ++ dma_addr_t adma_addr; ++ unsigned int desc_sz; /* ADMA descriptor size */ ++}; ++ ++enum adtc_t { ++ COMMOM_ADTC = 0, ++ BLOCK_RW_ADTC = 1 ++}; ++ ++enum phytmmc_msg_cmd_id { ++ PHYTMMC_MSG_CMD_DEFAULT = 0, ++ PHYTMMC_MSG_CMD_SET, ++ PHYTMMC_MSG_CMD_GET, ++ PHYTMMC_MSG_CMD_DATA, ++ PHYTMMC_MSG_CMD_REPORT ++}; ++ ++struct phyt_msg_info { ++ u8 reserved; ++ u8 seq; ++ u8 cmd_type; ++ u8 cmd_subid; ++ u16 len; ++ u8 status1; ++ u8 status0; ++#define NOT_READY 0x0 ++#define SUCCESS 0x1 ++#define GOING 0x2 ++#define GENERIC_ERROR 0x10 ++#define TYPE_NOT_SUPPORTED 0x11 ++#define CMD_NOT_SUPPORTED 0x12 ++#define INVALID_PARAMETERS 0x13 ++ u8 data[56]; ++}; ++ ++struct phytium_mci_host { ++ struct device *dev; ++ struct mmc_host *mmc; ++ u32 caps; ++ u32 caps2; ++ spinlock_t lock; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ int error; ++ void __iomem *base; /* host base address */ ++ void __iomem *regf_base; /* regfile base address */ ++ void *adma_table1; ++ dma_addr_t adma_addr1; ++ struct phytium_mci_dma dma_rx; /* dma channel */ ++ struct phytium_mci_dma dma_tx; /* dma channel */ ++ struct phytium_mci_dma dma; /* dma channel */ ++ u64 dma_mask; ++ bool vqmmc_enabled; ++ u32 *sg_virt_addr; ++ enum adtc_t adtc_type; /* 0:common adtc cmd; 1:block r/w adtc cmd;*/ ++ struct timer_list hotplug_timer; ++ struct delayed_work req_timeout; ++ int irq; /* host interrupt */ ++ u32 current_rca; /*the current rca value*/ ++ u32 current_ios_clk; ++ u32 is_use_dma; ++ u32 is_device_x100; ++ struct clk *src_clk; /* phytium_mci source clock */ ++ unsigned long clk_rate; ++ unsigned long clk_div; ++ unsigned long irq_flags; ++ unsigned long flags; ++#define MCI_CARD_NEED_INIT 1 ++ bool cmd_cs; /*volt switch cmd cs status*/ ++ bool use_hold; /*use hold*/ ++ bool clk_set; /*clock set*/ ++ s32 clk_smpl_drv_25m; ++ s32 clk_smpl_drv_50m; ++ s32 clk_smpl_drv_66m; ++ s32 clk_smpl_drv_100m; ++ struct phyt_msg_info msg; ++ struct phyt_msg_info rxmsg; ++ bool debug_enable; ++ bool alive_enable; ++ struct timer_list alive_timer; ++}; ++ ++int phyt_mci_common_probe(struct phytium_mci_host *host); ++void phyt_mci_deinit_hw(struct phytium_mci_host *host); ++int phyt_mci_runtime_suspend(struct device *dev); ++int phyt_mci_runtime_resume(struct device *dev); ++int phyt_mci_resume(struct device *dev); ++int phyt_mci_suspend(struct device *dev); ++int phytium_mci_set_debug_enable(struct phytium_mci_host *host, bool enable); ++int phytium_mci_set_alive_enable(struct phytium_mci_host *host, bool enable); ++ ++struct init_data_t { ++ uint32_t caps; ++ uint32_t clk_rate; ++}; ++ ++struct start_command_data_t { ++ uint32_t cmd_arg; ++ uint32_t cmd_flags; ++ uint32_t cmd_opcode; ++ uint32_t rawcmd; ++}; ++ ++struct start_data_data_t { ++ uint32_t data_flags; ++ uint32_t adtc_type; ++ uint64_t adma_addr; ++ uint32_t mrq_data_blksz; ++ uint32_t mrq_data_blocks; ++ uint32_t cmd_arg; ++ uint32_t rawcmd; ++}; ++ ++struct set_ios_data_t { ++ uint32_t ios_clock; ++ uint8_t ios_timing; ++ uint8_t ios_bus_width; ++ uint8_t ios_power_mode; ++}; ++ ++struct cmd_next_data_t { ++ uint32_t events; ++ uint32_t response0; ++ uint32_t response1; ++ uint32_t response2; ++ uint32_t response3; ++}; ++ ++struct err_irq_data_t { ++ uint32_t raw_ints; ++ uint32_t ints_mask; ++ uint32_t dmac_status; ++ uint32_t dmac_mask; ++ uint32_t opcode; ++}; ++#endif /* __PHYTIUM_MCI_HW_H */ +diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c +index febc7ed92e93..aa0211b023b4 100644 +--- a/drivers/mmc/host/phytium-mci.c ++++ b/drivers/mmc/host/phytium-mci.c +@@ -44,7 +44,7 @@ static const u32 data_ints_mask = MCI_INT_MASK_DTO | MCI_INT_MASK_DCRC | MCI_INT + MCI_INT_MASK_SBE_BCI; + static const u32 cmd_err_ints_mask = MCI_INT_MASK_RTO | MCI_INT_MASK_RCRC | MCI_INT_MASK_RE | + MCI_INT_MASK_DCRC | MCI_INT_MASK_DRTO | +- MCI_MASKED_INTS_SBE_BCI; ++ MCI_MASKED_INTS_SBE_BCI | MCI_MASKED_INTS_EBE; + + static const u32 dmac_ints_mask = MCI_DMAC_INT_ENA_FBE | MCI_DMAC_INT_ENA_DU | + MCI_DMAC_INT_ENA_NIS | MCI_DMAC_INT_ENA_AIS; +@@ -62,6 +62,7 @@ static void phytium_mci_init_adma_table(struct phytium_mci_host *host, + struct phytium_mci_dma *dma); + static void phytium_mci_init_hw(struct phytium_mci_host *host); + static int phytium_mci_get_cd(struct mmc_host *mmc); ++static int phytium_mci_get_ro(struct mmc_host *mmc); + static int phytium_mci_err_irq(struct phytium_mci_host *host, u32 dmac_events, u32 events); + + static void sdr_set_bits(void __iomem *reg, u32 bs) +@@ -178,7 +179,7 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i + host->clk_rate, ios->clock); + + if (ios->clock >= 25000000) +- tmp_ext_reg = 0x202; ++ tmp_ext_reg = 0x102; + else if (ios->clock == 400000) + tmp_ext_reg = 0x502; + else +@@ -226,8 +227,26 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i + } + } + +- dev_dbg(host->dev, "UHS_REG_EXT ext: %x, CLKDIV: %x\n", +- readl(host->base + MCI_UHS_REG_EXT), readl(host->base + MCI_CLKDIV)); ++ if (!(readl(host->base + MCI_CLKDIV) & 0xff00) && ++ (ios->timing == MMC_TIMING_MMC_DDR52 || ++ ios->timing == MMC_TIMING_MMC_HS400 || ++ ios->timing == MMC_TIMING_UHS_DDR50)) { ++ sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_CRC_SERIAL_DATA); ++ sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_DRV_SHIFT_EN); ++ } else { ++ sdr_clr_bits(host->base + MCI_CNTRL, MCI_CNTRL_CRC_SERIAL_DATA); ++ sdr_clr_bits(host->base + MCI_CNTRL, MCI_CNTRL_DRV_SHIFT_EN); ++ } ++ ++ if (div >= 2) ++ writel(((2 * (div & 0xff)) & 0xffff), host->base + MCI_CLK_DIVIDER); ++ ++ dev_dbg(host->dev, "UHS_REG_EXT ext: %x, CLKDIV: %x MCI_CLK_DIVIDER %x %x\n", ++ readl(host->base + MCI_UHS_REG_EXT), readl(host->base + MCI_CLKDIV), ++ readl(host->base + MCI_CLK_DIVIDER), ((2 * (div & 0xff)) & 0xffff)); ++ ++ if (cur_cmd_index == SD_SWITCH_VOLTAGE) ++ msleep(40); + + sdr_set_bits(host->base + MCI_CLKENA, MCI_CLKENA_CCLK_ENABLE); + +@@ -1260,6 +1279,7 @@ static void phytium_mci_init_hw(struct phytium_mci_host *host) + sdr_set_bits(host->base + MCI_CLKENA, MCI_CLKENA_CCLK_ENABLE); + sdr_set_bits(host->base + MCI_UHS_REG_EXT, MCI_EXT_CLK_ENABLE); + sdr_clr_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_VOLT); ++ sdr_clr_bits(host->base + MCI_EMMC_DDR_REG, MCI_EMMC_DDR_CYCLE); + + phytium_mci_reset_hw(host); + +@@ -1362,8 +1382,13 @@ static void phytium_mci_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct phytium_mci_host *host = mmc_priv(mmc); + +- if (ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_DDR50) ++ if (ios->timing == MMC_TIMING_MMC_DDR52 || ++ ios->timing == MMC_TIMING_MMC_HS400 || ++ ios->timing == MMC_TIMING_UHS_DDR50) { + sdr_set_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_DDR); ++ sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_START_BIT_MODE); ++ sdr_clr_bits(host->base + MCI_EMMC_DDR_REG, MCI_EMMC_DDR_CYCLE); ++ } + else + sdr_clr_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_DDR); + +@@ -1414,6 +1439,20 @@ static int phytium_mci_get_cd(struct mmc_host *mmc) + return 1; + } + ++static int phytium_mci_get_ro(struct mmc_host *mmc) ++{ ++ struct phytium_mci_host *host = mmc_priv(mmc); ++ u32 status; ++ ++ status = readl(host->base + MCI_CARD_WRTPRT); ++ ++ dev_dbg(host->dev, "mci_get_ro status %d\n", status); ++ if ((status & 0x1) == 0x1) ++ return 1; ++ ++ return 0; ++} ++ + static int phytium_mci_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct phytium_mci_host *host = mmc_priv(mmc); +@@ -1507,6 +1546,7 @@ static struct mmc_host_ops phytium_mci_ops = { + .request = phytium_mci_ops_request, + .set_ios = phytium_mci_ops_set_ios, + .get_cd = phytium_mci_get_cd, ++ .get_ro = phytium_mci_get_ro, + .enable_sdio_irq = phytium_mci_enable_sdio_irq, + .ack_sdio_irq = phytium_mci_ack_sdio_irq, + .card_busy = phytium_mci_card_busy, +@@ -1588,3 +1628,4 @@ EXPORT_SYMBOL(phytium_mci_common_probe); + MODULE_DESCRIPTION("Phytium Multimedia Card Interface driver"); + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Cheng Quan "); ++MODULE_VERSION(PHYTIUM_MMC_DRIVER_VERSION); +diff --git a/drivers/mmc/host/phytium-mci.h b/drivers/mmc/host/phytium-mci.h +index 90f51b9ee135..5bf6df4540c3 100644 +--- a/drivers/mmc/host/phytium-mci.h ++++ b/drivers/mmc/host/phytium-mci.h +@@ -19,6 +19,8 @@ + /*------------------------------------------------------*/ + /* Common Definition */ + /*------------------------------------------------------*/ ++#define PHYTIUM_MMC_DRIVER_VERSION "1.0.0" ++ + #define MAX_BD_NUM 128 + #define SD_BLOCK_SIZE 512 + +@@ -104,6 +106,7 @@ + #define MCI_UHS_REG_EXT 0x108 /* the UHS register extension */ + #define MCI_EMMC_DDR_REG 0x10C /* the EMMC DDR reg */ + #define MCI_ENABLE_SHIFT 0x110 /* the enable phase shift reg */ ++#define MCI_CLK_DIVIDER 0x114 /* CLK DIVIDER */ + #define MCI_DATA 0x200 /* the data FIFO access */ + + /* Command register defines */ +@@ -132,12 +135,14 @@ + #define MCI_CNTRL_CONTROLLER_RESET (0x1 << 0) /* RW */ + #define MCI_CNTRL_FIFO_RESET (0x1 << 1) /* RW */ + #define MCI_CNTRL_DMA_RESET (0x1 << 2) /* RW */ +-#define MCI_CNTRL_RES (0x1 << 3) /* */ ++#define MCI_CNTRL_DRV_SHIFT_EN (0x1 << 3) /* */ + #define MCI_CNTRL_INT_ENABLE (0x1 << 4) /* RW */ + #define MCI_CNTRL_DMA_ENABLE (0x1 << 5) /* RW */ + #define MCI_CNTRL_READ_WAIT (0x1 << 6) /* RW */ + #define MCI_CNTRL_SEND_IRQ_RESPONSE (0x1 << 7) /* RW */ + #define MCI_CNTRL_ABORT_READ_DATA (0x1 << 8) /* RW */ ++#define MCI_CNTRL_START_BIT_MODE (0x1 << 9) /* RW */ ++#define MCI_CNTRL_CRC_SERIAL_DATA (0x1 << 10) /* RW */ + #define MCI_CNTRL_ENDIAN (0x1 << 11) /* RW */ + //#define MCI_CNTRL_CARD_VOLTAGE_A (0xF << 16) /* RW */ + //#define MCI_CNTRL_CARD_VOLTAGE_B (0xF << 20) /* RW */ +diff --git a/drivers/mmc/host/phytium-sdci.c b/drivers/mmc/host/phytium-sdci.c +index b4ca402c1da5..45e859aecda4 100755 +--- a/drivers/mmc/host/phytium-sdci.c ++++ b/drivers/mmc/host/phytium-sdci.c +@@ -34,6 +34,8 @@ + + #include "phytium-sdci.h" + ++#define PHYTIUM_SDCI_DRIVER_VERSION "1.0.0" ++ + static const u32 cmd_ints_mask = SDCI_SDCI_NORMAL_ISER_ECC_EN | SDCI_SDCI_NORMAL_ISER_EEI_EN; + static const u32 data_ints_mask = SDCI_BD_ISER_ETRS_EN; + static const u32 err_ints_mask = SDCI_ERROR_ISER_ECTE_EN | SDCI_ERROR_ISR_CCRCE_EN | +@@ -1431,3 +1433,4 @@ MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Cheng Quan "); + MODULE_AUTHOR("Chen Baozi "); + MODULE_DESCRIPTION("Phytium SD Card Interface driver"); ++MODULE_VERSION(PHYTIUM_SDCI_DRIVER_VERSION); +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index c9f3d1772a0c..bfa39ffd64be 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -53,7 +53,7 @@ struct sifive_fu540_macb_mgmt { + #define RX_BUFFER_MULTIPLE 64 /* bytes */ + + #define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */ +-#define MIN_RX_RING_SIZE 64 ++#define MIN_RX_RING_SIZE 128 + #define MAX_RX_RING_SIZE 8192 + #define RX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \ + * (bp)->rx_ring_size) +@@ -106,6 +106,10 @@ struct sifive_fu540_macb_mgmt { + + #define MACB_MDIO_TIMEOUT 1000000 /* in usecs */ + ++static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb); ++static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, ++ dma_addr_t addr); ++ + /* DMA buffer descriptor might be different size + * depends on hardware configuration: + * +@@ -749,7 +753,7 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode, + * otherwise writes will not take effect. + */ + if (macb_is_gem(bp) && (state->interface == PHY_INTERFACE_MODE_SGMII || +- PHY_INTERFACE_MODE_2500BASEX)) { ++ state->interface == PHY_INTERFACE_MODE_2500BASEX)) { + u32 pcsctrl, old_pcsctrl; + + old_pcsctrl = gem_readl(bp, PCSCNTRL); +@@ -769,9 +773,12 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, + { + struct net_device *ndev = to_net_dev(config->dev); + struct macb *bp = netdev_priv(ndev); ++ struct macb_tx_skb *tx_skb; + struct macb_queue *queue; ++ struct macb_dma_desc *tx_desc = NULL; + unsigned int q; + u32 ctrl; ++ int i; + + if (bp->use_ncsi) + ncsi_stop_dev(bp->ndev); +@@ -785,6 +792,22 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, + ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE)) & ~(MACB_BIT(2PT5G)); + macb_writel(bp, NCR, ctrl); + ++ /* Tx clean */ ++ spin_lock(&bp->lock); ++ for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { ++ for (i = 0; i < bp->tx_ring_size; i++) { ++ tx_skb = macb_tx_skb(queue, i); ++ /* free unsent skb buffers */ ++ if (tx_skb) ++ macb_tx_unmap(bp, tx_skb); ++ ++ tx_desc = macb_tx_desc(queue, i); ++ macb_set_addr(bp, tx_desc, 0); ++ tx_desc->ctrl &= ~MACB_BIT(TX_USED); ++ } ++ } ++ spin_unlock(&bp->lock); ++ + netif_tx_stop_all_queues(ndev); + } + +@@ -824,7 +847,21 @@ static void phytium_gem1p0_sel_clk(struct macb *bp, int speed) + gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ + gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ + } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { +- if (speed == SPEED_1000) { ++ if (speed == SPEED_2500) { ++ gem_writel(bp, DIV_SEL0_LN, 0x1); /*0x1c08*/ ++ gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ ++ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ ++ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ ++ gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ ++ gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/ ++ gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/ ++ gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/ ++ gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/ ++ gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/ ++ gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/ ++ gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ ++ gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ ++ } else if (speed == SPEED_1000) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/ +@@ -996,10 +1033,16 @@ static void macb_mac_link_up(struct phylink_config *config, + + if (speed == SPEED_2500) { + u32 network_ctrl; ++ u32 pcsctrl, old_pcsctrl; + + network_ctrl = macb_readl(bp, NCR); + network_ctrl |= MACB_BIT(2PT5G); + macb_writel(bp, NCR, network_ctrl); ++ ++ old_pcsctrl = gem_readl(bp, PCSCNTRL); ++ pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); ++ if (old_pcsctrl != pcsctrl) ++ gem_writel(bp, PCSCNTRL, pcsctrl); + } + + if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER || +@@ -1135,10 +1178,11 @@ static int macb_mii_probe(struct net_device *dev) + bp->phylink_config.dev = &dev->dev; + bp->phylink_config.type = PHYLINK_NETDEV; + +- if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { ++ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII || ++ bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + bp->phylink_config.poll_fixed_state = true; + bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; +- } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX || ++ } else if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER || + bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { + bp->phylink_config.poll_fixed_state = true; + bp->phylink_config.get_fixed_state = macb_get_usx_pcs_fixed_state; +@@ -1944,27 +1988,27 @@ static void macb_hresp_error_task(struct tasklet_struct *t) + netif_tx_start_all_queues(dev); + } + +-static void macb_tx_restart(struct macb_queue *queue) ++static int macb_tx_restart(struct macb_queue *queue) + { + unsigned int head = queue->tx_head; + unsigned int tail = queue->tx_tail; + struct macb *bp = queue->bp; + unsigned int head_idx, tbqp; + +- if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) +- queue_writel(queue, ISR, MACB_BIT(TXUBR)); +- + if (head == tail) +- return; ++ return -ENXIO; + +- tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp); ++ tbqp = queue_readl(queue, TBQP) - lower_32_bits(queue->tx_ring_dma); ++ tbqp = tbqp / macb_dma_desc_get_size(bp); + tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp)); + head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head)); + + if (tbqp == head_idx) +- return; ++ return -ENXIO; + + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); ++ ++ return 0; + } + + static irqreturn_t macb_wol_interrupt(int irq, void *dev_id) +@@ -2027,10 +2071,11 @@ static irqreturn_t gem_wol_interrupt(int irq, void *dev_id) + + static irqreturn_t macb_interrupt(int irq, void *dev_id) + { +- struct macb_queue *queue = dev_id; ++ struct macb_queue *qq, *queue = dev_id; + struct macb *bp = queue->bp; + struct net_device *dev = bp->dev; + u32 status, ctrl; ++ int q; + + status = queue_readl(queue, ISR); + +@@ -2082,8 +2127,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) + if (status & MACB_BIT(TCOMP)) + macb_tx_interrupt(queue); + +- if (status & MACB_BIT(TXUBR)) +- macb_tx_restart(queue); ++ if (status & MACB_BIT(TXUBR)) { ++ if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) ++ queue_writel(queue, ISR, MACB_BIT(TXUBR)); ++ ++ for (q = 0, qq = bp->queues; q < bp->num_queues; ++q, ++qq) ++ if (!macb_tx_restart(qq)) ++ break; ++ } + + /* Link change detection isn't possible with RMII, so we'll + * add that if/when we get our hands on a full-blown MII PHY. +@@ -3022,6 +3073,10 @@ static void macb_init_hw(struct macb *bp) + macb_reset_hw(bp); + macb_set_hwaddr(bp); + ++ config = macb_readl(bp, NCR); ++ config |= MACB_BIT(MPE); ++ macb_writel(bp, NCR, config); ++ + config = macb_mdc_clk_div(bp); + config |= MACB_BF(RBOF, NET_IP_ALIGN); /* Make eth data aligned */ + config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ +@@ -3522,17 +3577,68 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + static int macb_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *kset) + { ++ int ret = 0; + struct macb *bp = netdev_priv(netdev); ++ u32 supported = 0; ++ u32 advertising = 0; ++ ++ if (!phylink_expects_phy(bp->phylink)) { ++ if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || ++ bp->phy_interface == PHY_INTERFACE_MODE_XGMII) { ++ supported = SUPPORTED_10000baseT_Full ++ | SUPPORTED_FIBRE | SUPPORTED_Pause; ++ advertising = ADVERTISED_10000baseT_Full ++ | ADVERTISED_FIBRE | ADVERTISED_Pause; ++ kset->base.port = PORT_FIBRE; ++ kset->base.transceiver = XCVR_INTERNAL; ++ } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { ++ supported = SUPPORTED_2500baseX_Full | SUPPORTED_1000baseT_Full ++ | SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Full ++ | SUPPORTED_FIBRE | SUPPORTED_Pause; ++ advertising = ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full ++ | ADVERTISED_100baseT_Full | ADVERTISED_10baseT_Full ++ | ADVERTISED_FIBRE | ADVERTISED_Pause; ++ kset->base.port = PORT_FIBRE; ++ kset->base.transceiver = XCVR_INTERNAL; ++ } else if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII) { ++ supported = SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full ++ | SUPPORTED_10baseT_Full | SUPPORTED_TP; ++ advertising = ADVERTISED_1000baseT_Full | ADVERTISED_100baseT_Full ++ | ADVERTISED_10baseT_Full | ADVERTISED_TP; ++ } else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) { ++ supported = SUPPORTED_100baseT_Full ++ | SUPPORTED_10baseT_Full | SUPPORTED_TP; ++ advertising = ADVERTISED_100baseT_Full ++ | ADVERTISED_10baseT_Full | ADVERTISED_TP; ++ } + +- return phylink_ethtool_ksettings_get(bp->phylink, kset); ++ ethtool_convert_legacy_u32_to_link_mode(kset->link_modes.supported, ++ supported); ++ ethtool_convert_legacy_u32_to_link_mode(kset->link_modes.advertising, ++ advertising); ++ kset->base.speed = bp->speed; ++ kset->base.duplex = bp->duplex; ++ } else { ++ phylink_ethtool_ksettings_get(bp->phylink, kset); ++ } ++ ++ return ret; + } + + static int macb_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *kset) + { + struct macb *bp = netdev_priv(netdev); ++ int ret = 0; ++ ++ if (!phylink_expects_phy(bp->phylink)) { ++ netdev_err(netdev, "fixed link interface not supported set link\n"); ++ ret = -EOPNOTSUPP; ++ } else { ++ ret = phylink_ethtool_ksettings_set(bp->phylink, kset); ++ } + +- return phylink_ethtool_ksettings_set(bp->phylink, kset); ++ return ret; + } + + static void macb_get_ringparam(struct net_device *netdev, +@@ -4183,6 +4289,75 @@ static void macb_probe_queues(void __iomem *mem, + *num_queues = hweight32(*queue_mask); + } + ++#ifdef CONFIG_ACPI ++static int macb_clk_acpi_init(struct platform_device *pdev, struct clk **pclk, ++ struct clk **hclk, struct clk **tx_clk, ++ struct clk **rx_clk, struct clk **tsu_clk) ++{ ++ struct macb_platform_data *pdata; ++ int err; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ if (pdata) { ++ *pclk = pdata->pclk; ++ *hclk = pdata->hclk; ++ } else { ++ *pclk = NULL; ++ *hclk = NULL; ++ } ++ ++ *tx_clk = NULL; ++ *rx_clk = NULL; ++ *tsu_clk = NULL; ++ ++ err = clk_prepare_enable(*pclk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err); ++ return err; ++ } ++ ++ err = clk_prepare_enable(*hclk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", err); ++ goto err_disable_pclk; ++ } ++ ++ err = clk_prepare_enable(*tx_clk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to enable tx_clk (%d)\n", err); ++ goto err_disable_hclk; ++ } ++ ++ err = clk_prepare_enable(*rx_clk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err); ++ goto err_disable_txclk; ++ } ++ ++ err = clk_prepare_enable(*tsu_clk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to enable tsu_clk (%d)\n", err); ++ goto err_disable_rxclk; ++ } ++ ++ return 0; ++ ++err_disable_rxclk: ++ clk_disable_unprepare(*rx_clk); ++ ++err_disable_txclk: ++ clk_disable_unprepare(*tx_clk); ++ ++err_disable_hclk: ++ clk_disable_unprepare(*hclk); ++ ++err_disable_pclk: ++ clk_disable_unprepare(*pclk); ++ ++ return err; ++} ++#endif ++ + static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, + struct clk **hclk, struct clk **tx_clk, + struct clk **rx_clk, struct clk **tsu_clk) +@@ -5040,6 +5215,21 @@ static const struct macb_config phytium_gem1p0_config = { + .sel_clk_hw = phytium_gem1p0_sel_clk, + }; + ++#ifdef CONFIG_ACPI ++static const struct macb_config phytium_gem1p0_acpi_config = { ++ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | ++ MACB_CAPS_JUMBO | ++ MACB_CAPS_GEM_HAS_PTP | ++ MACB_CAPS_BD_RD_PREFETCH | ++ MACB_CAPS_SEL_CLK, ++ .dma_burst_length = 16, ++ .clk_init = macb_clk_acpi_init, ++ .init = macb_init, ++ .jumbo_max_len = 10240, ++ .sel_clk_hw = phytium_gem1p0_sel_clk, ++}; ++#endif ++ + static const struct macb_config phytium_gem2p0_config = { + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | + MACB_CAPS_JUMBO | +@@ -5070,6 +5260,7 @@ static const struct of_device_id macb_dt_ids[] = { + { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config}, + { .compatible = "cdns,zynq-gem", .data = &zynq_config }, + { .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config }, ++ { .compatible = "cdns,phytium-gem", .data = &phytium_gem1p0_config }, /* old version */ + { .compatible = "cdns,phytium-gem-1.0", .data = &phytium_gem1p0_config }, + { .compatible = "cdns,phytium-gem-2.0", .data = &phytium_gem2p0_config }, + { /* sentinel */ } +@@ -5079,7 +5270,7 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids); + + #ifdef CONFIG_ACPI + static const struct acpi_device_id macb_acpi_ids[] = { +- { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_gem1p0_config }, ++ { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_gem1p0_acpi_config }, + { } + }; + +@@ -5132,7 +5323,7 @@ static int macb_probe(struct platform_device *pdev) + struct clk **) = macb_config->clk_init; + int (*init)(struct platform_device *) = macb_config->init; + struct device_node *np = pdev->dev.of_node; +- struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL; ++ struct clk *pclk = NULL, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL; + struct clk *tsu_clk = NULL; + unsigned int queue_mask, num_queues; + bool native_io; +@@ -5369,11 +5560,16 @@ static int macb_remove(struct platform_device *pdev) + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + if (!pm_runtime_suspended(&pdev->dev)) { +- clk_disable_unprepare(bp->tx_clk); +- clk_disable_unprepare(bp->hclk); +- clk_disable_unprepare(bp->pclk); +- clk_disable_unprepare(bp->rx_clk); +- clk_disable_unprepare(bp->tsu_clk); ++ if (__clk_is_enabled(bp->tx_clk)) ++ clk_disable_unprepare(bp->tx_clk); ++ if (__clk_is_enabled(bp->hclk)) ++ clk_disable_unprepare(bp->hclk); ++ if (__clk_is_enabled(bp->pclk)) ++ clk_disable_unprepare(bp->pclk); ++ if (__clk_is_enabled(bp->rx_clk)) ++ clk_disable_unprepare(bp->rx_clk); ++ if (__clk_is_enabled(bp->tsu_clk)) ++ clk_disable_unprepare(bp->tsu_clk); + pm_runtime_set_suspended(&pdev->dev); + } + phylink_destroy(bp->phylink); +@@ -5553,12 +5749,17 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev) + struct macb *bp = netdev_priv(netdev); + + if (!(device_may_wakeup(dev))) { +- clk_disable_unprepare(bp->tx_clk); +- clk_disable_unprepare(bp->hclk); +- clk_disable_unprepare(bp->pclk); +- clk_disable_unprepare(bp->rx_clk); ++ if (__clk_is_enabled(bp->tx_clk)) ++ clk_disable_unprepare(bp->tx_clk); ++ if (__clk_is_enabled(bp->hclk)) ++ clk_disable_unprepare(bp->hclk); ++ if (__clk_is_enabled(bp->pclk)) ++ clk_disable_unprepare(bp->pclk); ++ if (__clk_is_enabled(bp->rx_clk)) ++ clk_disable_unprepare(bp->rx_clk); + } +- clk_disable_unprepare(bp->tsu_clk); ++ if (__clk_is_enabled(bp->tsu_clk)) ++ clk_disable_unprepare(bp->tsu_clk); + + return 0; + } +diff --git a/drivers/net/ethernet/phytium/Kconfig b/drivers/net/ethernet/phytium/Kconfig +index d3f16d0f79a8..9e426b4b2ad8 100644 +--- a/drivers/net/ethernet/phytium/Kconfig ++++ b/drivers/net/ethernet/phytium/Kconfig +@@ -12,7 +12,7 @@ config NET_VENDOR_PHYTIUM + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all the +- remaining Cadence network card questions. If you say Y, you will be ++ remaining Phytium network card questions. If you say Y, you will be + asked for your specific card in the following questions. + + if NET_VENDOR_PHYTIUM +@@ -20,7 +20,6 @@ if NET_VENDOR_PHYTIUM + config PHYTMAC + tristate "Phytium GMAC support" + depends on HAS_DMA +- #depends on PTP_1588_CLOCK_OPTIONAL + select PHYLINK + select CRC32 + help +@@ -56,18 +55,4 @@ config PHYTMAC_PCI + To compile this driver as a module, choose M here: the module + will be called phytmac_pci. + +-#config PHYTMAC_1P0 +-# bool "Phytmac 1p0 support" +-# depends on PHYTMAC +-# default y +-# help +-# To compile this driver as a module, choose M here: the module +- +-#config PHYTMAC_2P0 +-# bool "Phytmac 2p0 support" +-# depends on PHYTMAC +-# default y +-# help +-# To compile this driver as a module, choose M here: the module +- + endif # NET_VENDOR_PHYTIUM +diff --git a/drivers/net/ethernet/phytium/Makefile b/drivers/net/ethernet/phytium/Makefile +index 6e710d4d54b6..debaed63e453 100644 +--- a/drivers/net/ethernet/phytium/Makefile ++++ b/drivers/net/ethernet/phytium/Makefile +@@ -1,9 +1,9 @@ + + # SPDX-License-Identifier: GPL-2.0 ++# Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. + # + # Makefile for the Phytium network device drivers. + # +-# + + obj-$(CONFIG_PHYTMAC) += phytmac.o + +diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h +index 97a7526099d1..79a360460f26 100644 +--- a/drivers/net/ethernet/phytium/phytmac.h ++++ b/drivers/net/ethernet/phytium/phytmac.h +@@ -1,4 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ ++ + #ifndef _PHYTMAC_H + #define _PHYTMAC_H + +@@ -10,10 +12,12 @@ + #include + #include + #include ++#include + +-#define PHYTMAC_DRV_NAME "phytium-mac" ++#define PHYTMAC_PCI_DRV_NAME "phytmac_pci" ++#define PHYTMAC_PLAT_DRV_NAME "phytmac_platform" + #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" +-#define PHYTMAC_DRIVER_VERSION "1.0.5" ++#define PHYTMAC_DRIVER_VERSION "1.0.45" + #define PHYTMAC_DEFAULT_MSG_ENABLE \ + (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ +@@ -44,11 +48,15 @@ + + #define PHYTMAC_POWEROFF 1 + #define PHYTMAC_POWERON 2 ++#define PHYTMAC_PWCTL_GMAC_ID 6 ++#define PHYTMAC_PWCTL_DEFAULT_VAL 0 + + #define PHYTMAC_WOL_MAGIC_PACKET 1 + + #define DEFAULT_MSG_RING_SIZE 16 + ++#define PHYTMAC_MDIO_TIMEOUT 1000000 /* in usecs */ ++ + #define PHYTMAC_CAPS_JUMBO 0x00000001 + #define PHYTMAC_CAPS_PTP 0x00000002 + #define PHYTMAC_CAPS_BD_RD_PREFETCH 0x00000004 +@@ -58,13 +66,18 @@ + #define PHYTMAC_CAPS_TAILPTR 0x00000040 + #define PHYTMAC_CAPS_START 0x00000080 + #define PHYTMAC_CAPS_NO_WOL 0x0000100 +-#define PHYTMAC_CAPS_LPI 0x0000400 ++#define PHYTMAC_CAPS_PWCTRL 0x0000200 + #define PHYTMAC_CAPS_MSG 0x0000800 ++#define PHYTMAC_CAPS_RXPTR 0x0001000 ++ ++#define VERSION_V0 0 ++#define VERSION_V3 0x3 + + #define PHYTMAC_TX 0x1 + #define PHYTMAC_RX 0x2 + +-#define PHYTMAC_GREGS_LEN 16 ++#define PHYTMAC_ETHTOOLD_REGS_LEN 64 ++#define PHYTMAC_STATIS_REG_NUM 45 + + #define PHYTMAC_MTU_MIN_SIZE ETH_MIN_MTU + +@@ -102,9 +115,6 @@ + #define PHYTMAC_MSG_READ(_pdata, _reg) \ + __raw_readl((_pdata)->mac_regs + (_reg)) + +-#define PHYTMAC_WRITE(_pdata, _reg, _val) \ +- __raw_writel((_val), (_pdata)->mac_regs + (_reg)) +- + #define LSO_UFO 1 + #define LSO_TSO 2 + +@@ -122,6 +132,47 @@ + #define PHYTMAC_WAKE_UCAST 0x00000004 + #define PHYTMAC_WAKE_MCAST 0x00000008 + ++/* XDP */ ++#define PHYTMAC_XDP_PASS 0 ++#define PHYTMAC_XDP_CONSUMED BIT(0) ++#define PHYTMAC_XDP_TX BIT(1) ++#define PHYTMAC_XDP_REDIR BIT(2) ++ ++#define PHYTMAC_DESC_NEEDED (MAX_SKB_FRAGS + 4) ++ ++enum phytmac_interface { ++ PHYTMAC_PHY_INTERFACE_MODE_NA, ++ PHYTMAC_PHY_INTERFACE_MODE_INTERNAL, ++ PHYTMAC_PHY_INTERFACE_MODE_MII, ++ PHYTMAC_PHY_INTERFACE_MODE_GMII, ++ PHYTMAC_PHY_INTERFACE_MODE_SGMII, ++ PHYTMAC_PHY_INTERFACE_MODE_TBI, ++ PHYTMAC_PHY_INTERFACE_MODE_REVMII, ++ PHYTMAC_PHY_INTERFACE_MODE_RMII, ++ PHYTMAC_PHY_INTERFACE_MODE_RGMII, ++ PHYTMAC_PHY_INTERFACE_MODE_RGMII_ID, ++ PHYTMAC_PHY_INTERFACE_MODE_RGMII_RXID, ++ PHYTMAC_PHY_INTERFACE_MODE_RGMII_TXID, ++ PHYTMAC_PHY_INTERFACE_MODE_RTBI, ++ PHYTMAC_PHY_INTERFACE_MODE_SMII, ++ PHYTMAC_PHY_INTERFACE_MODE_XGMII, ++ PHYTMAC_PHY_INTERFACE_MODE_MOCA, ++ PHYTMAC_PHY_INTERFACE_MODE_QSGMII, ++ PHYTMAC_PHY_INTERFACE_MODE_TRGMII, ++ PHYTMAC_PHY_INTERFACE_MODE_100BASEX, ++ PHYTMAC_PHY_INTERFACE_MODE_1000BASEX, ++ PHYTMAC_PHY_INTERFACE_MODE_2500BASEX, ++ PHYTMAC_PHY_INTERFACE_MODE_5GBASER, ++ PHYTMAC_PHY_INTERFACE_MODE_RXAUI, ++ PHYTMAC_PHY_INTERFACE_MODE_XAUI, ++ /* 10GBASE-R, XFI, SFI - single lane 10G Serdes */ ++ PHYTMAC_PHY_INTERFACE_MODE_10GBASER, ++ PHYTMAC_PHY_INTERFACE_MODE_USXGMII, ++ /* 10GBASE-KR - with Clause 73 AN */ ++ PHYTMAC_PHY_INTERFACE_MODE_10GKR, ++ PHYTMAC_PHY_INTERFACE_MODE_MAX, ++}; ++ + struct packet_info { + int lso; + int desc_cnt; +@@ -214,7 +265,6 @@ static const struct phytmac_statistics queue_statistics[] = { + struct phytmac_config { + struct phytmac_hw_if *hw_if; + u32 caps; +- u32 tsu_rate; + u16 queue_num; + }; + +@@ -294,8 +344,20 @@ struct phytmac_dma_desc { + }; + #endif + ++/* TX resources are shared between XDP and netstack ++ * and we need to tag the buffer type to distinguish them ++ */ ++enum phytmac_tx_buf_type { ++ PHYTMAC_TYPE_SKB = 0, ++ PHYTMAC_TYPE_XDP, ++}; ++ + struct phytmac_tx_skb { +- struct sk_buff *skb; ++ union { ++ struct sk_buff *skb; ++ struct xdp_frame *xdpf; ++ }; ++ enum phytmac_tx_buf_type type; + dma_addr_t addr; + size_t length; + bool mapped_as_page; +@@ -318,6 +380,7 @@ struct phytmac_queue { + struct phytmac *pdata; + int irq; + int index; ++ struct bpf_prog *xdp_prog; + + /* tx queue info */ + unsigned int tx_head; +@@ -340,6 +403,7 @@ struct phytmac_queue { + struct phytmac_rx_buffer *rx_buffer_info; + struct napi_struct rx_napi; + struct phytmac_queue_stats stats; ++ struct xdp_rxq_info xdp_rxq; + + #ifdef CONFIG_PHYTMAC_ENABLE_PTP + struct work_struct tx_ts_task; +@@ -364,11 +428,12 @@ struct phytmac_msg { + u32 tx_msg_ring_size; + u32 rx_msg_ring_size; + u32 tx_msg_head; +- u32 tx_msg_tail; ++ u32 tx_msg_wr_tail; ++ u32 tx_msg_rd_tail; + u32 rx_msg_head; + u32 rx_msg_tail; +- /* Lock to protect msg */ +- spinlock_t msg_lock; ++ /* use msg_lock to protect msg */ ++ spinlock_t msg_lock; + }; + + struct ts_ctrl { +@@ -385,6 +450,7 @@ struct phytmac { + struct platform_device *platdev; + struct net_device *ndev; + struct device *dev; ++ struct bpf_prog *xdp_prog; + struct ncsi_dev *ncsidev; + struct fwnode_handle *fwnode; + struct phytmac_hw_if *hw_if; +@@ -401,13 +467,10 @@ struct phytmac { + u32 min_tx_length; + u32 jumbo_len; + u32 wol; +- u32 lpi; + u32 power_state; + struct work_struct restart_task; + /* Lock to protect mac config */ + spinlock_t lock; +- /* Lock to protect msg tx */ +- spinlock_t msg_lock; + u32 rx_ring_size; + u32 tx_ring_size; + u32 dma_data_width; +@@ -430,6 +493,7 @@ struct phytmac { + struct phylink_pcs phylink_pcs; + int pause; + phy_interface_t phy_interface; ++ enum phytmac_interface phytmac_v2_interface; + int speed; + int duplex; + int autoneg; +@@ -446,8 +510,27 @@ struct phytmac { + /* Lock to protect fs */ + spinlock_t rx_fs_lock; + unsigned int max_rx_fs; ++ u32 version; ++ char fw_version[32]; + }; + ++/* phytmac_desc_unused - calculate if we have unused descriptors */ ++static inline int phytmac_txdesc_unused(struct phytmac_queue *queue) ++{ ++ struct phytmac *pdata = queue->pdata; ++ ++ if (queue->tx_head > queue->tx_tail) ++ return queue->tx_head - queue->tx_tail - 1; ++ ++ return pdata->tx_ring_size + queue->tx_head - queue->tx_tail - 1; ++} ++ ++static inline struct netdev_queue *phytmac_get_txq(const struct phytmac *pdata, ++ struct phytmac_queue *queue) ++{ ++ return netdev_get_tx_queue(pdata->ndev, queue->index); ++} ++ + struct phytmac_hw_if { + int (*init_msg_ring)(struct phytmac *pdata); + int (*init_hw)(struct phytmac *pdata); +@@ -490,6 +573,7 @@ struct phytmac_hw_if { + + /* mido ops */ + int (*enable_mdio_control)(struct phytmac *pdata, int enable); ++ int (*mdio_idle)(struct phytmac *pdata); + int (*mdio_read)(struct phytmac *pdata, int mii_id, int regnum, int is_c45); + int (*mdio_write)(struct phytmac *pdata, int mii_id, + int regnum, int is_c45, u16 data); +@@ -504,7 +588,7 @@ struct phytmac_hw_if { + void (*init_rx_map)(struct phytmac_queue *queue, u32 index); + unsigned int (*rx_map)(struct phytmac_queue *queue, u32 index, dma_addr_t addr); + void (*transmit)(struct phytmac_queue *queue); +- void (*restart)(struct phytmac *pdata); ++ void (*update_rx_tail)(struct phytmac_queue *queue); + int (*tx_complete)(const struct phytmac_dma_desc *desc); + bool (*rx_complete)(const struct phytmac_dma_desc *desc); + int (*get_rx_pkt_len)(struct phytmac *pdata, const struct phytmac_dma_desc *desc); +@@ -514,6 +598,7 @@ struct phytmac_hw_if { + bool (*rx_pkt_start)(const struct phytmac_dma_desc *desc); + bool (*rx_pkt_end)(const struct phytmac_dma_desc *desc); + unsigned int (*zero_rx_desc_addr)(struct phytmac_dma_desc *desc); ++ unsigned int (*zero_tx_desc)(struct phytmac_dma_desc *desc); + void (*clear_rx_desc)(struct phytmac_queue *queue, int begin, int end); + void (*clear_tx_desc)(struct phytmac_queue *queue); + /* ptp */ +@@ -582,6 +667,7 @@ struct phytmac_hw_if { + #define PHYTMAC_RX_DMA_ATTR \ + (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) + #define PHYTMAC_SKB_PAD (NET_SKB_PAD) ++#define PHYTMAC_ETH_PKT_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2)) + + #define PHYTMAC_RXBUFFER_2048 2048 + #define PHYTMAC_MAX_FRAME_BUILD_SKB \ +@@ -590,6 +676,10 @@ struct phytmac_hw_if { + #define PHYTMAC_RX_PAGE_ORDER 0 + #define PHYTMAC_RX_PAGE_SIZE (PAGE_SIZE << PHYTMAC_RX_PAGE_ORDER) + ++#define phytmac_ioremap_np(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRnE)) ++ ++void __iomem * ++phytmac_devm_ioremap_resource_np(struct device *dev, const struct resource *res); + struct phytmac_tx_skb *phytmac_get_tx_skb(struct phytmac_queue *queue, + unsigned int index); + struct phytmac_dma_desc *phytmac_get_tx_desc(struct phytmac_queue *queue, +@@ -601,6 +691,7 @@ int phytmac_drv_probe(struct phytmac *pdata); + int phytmac_drv_remove(struct phytmac *pdata); + int phytmac_drv_suspend(struct phytmac *pdata); + int phytmac_drv_resume(struct phytmac *pdata); ++void phytmac_drv_shutdown(struct phytmac *pdata); + struct phytmac *phytmac_alloc_pdata(struct device *dev); + void phytmac_free_pdata(struct phytmac *pdata); + int phytmac_reset_ringsize(struct phytmac *pdata, u32 rx_size, u32 tx_size); +diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c +index d88c92858752..2cc224c96aba 100644 +--- a/drivers/net/ethernet/phytium/phytmac_ethtool.c ++++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0-only ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ + + #include + #include +@@ -69,7 +70,7 @@ static void phytmac_get_ethtool_strings(struct net_device *ndev, u32 sset, u8 *p + + static inline int phytmac_get_regs_len(struct net_device *ndev) + { +- return PHYTMAC_GREGS_LEN; ++ return PHYTMAC_ETHTOOLD_REGS_LEN; + } + + static void phytmac_get_regs(struct net_device *ndev, +@@ -80,7 +81,7 @@ static void phytmac_get_regs(struct net_device *ndev, + struct phytmac_hw_if *hw_if = pdata->hw_if; + u32 *regs_buff = p; + +- memset(p, 0, PHYTMAC_GREGS_LEN * sizeof(u32)); ++ memset(p, 0, PHYTMAC_ETHTOOLD_REGS_LEN); + + hw_if->get_regs(pdata, regs_buff); + } +@@ -89,24 +90,20 @@ static void phytmac_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol + { + struct phytmac *pdata = netdev_priv(ndev); + ++ wol->wolopts = 0; + phylink_ethtool_get_wol(pdata->phylink, wol); + +- if (pdata->wol & PHYTMAC_WAKE_MAGIC) { ++ wol->supported = WAKE_MAGIC | WAKE_ARP | ++ WAKE_UCAST | WAKE_MCAST; ++ ++ if (pdata->wol & PHYTMAC_WAKE_MAGIC) + wol->wolopts |= WAKE_MAGIC; +- wol->supported |= WAKE_MAGIC; +- } +- if (pdata->wol & PHYTMAC_WAKE_ARP) { ++ if (pdata->wol & PHYTMAC_WAKE_ARP) + wol->wolopts |= WAKE_ARP; +- wol->supported |= WAKE_ARP; +- } +- if (pdata->wol & PHYTMAC_WAKE_UCAST) { ++ if (pdata->wol & PHYTMAC_WAKE_UCAST) + wol->wolopts |= WAKE_UCAST; +- wol->supported |= WAKE_UCAST; +- } +- if (pdata->wol & PHYTMAC_WAKE_MCAST) { ++ if (pdata->wol & PHYTMAC_WAKE_MCAST) + wol->wolopts |= WAKE_MCAST; +- wol->supported |= WAKE_MCAST; +- } + } + + static int phytmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +@@ -116,7 +113,8 @@ static int phytmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) + + ret = phylink_ethtool_set_wol(pdata->phylink, wol); + +- if (!ret || ret != -EOPNOTSUPP) ++ /* Don't manage WoL on MAC, if PHY set_wol() fails */ ++ if (ret && ret != -EOPNOTSUPP) + return ret; + + pdata->wol = 0; +@@ -505,13 +503,16 @@ static void phytmac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo + { + struct phytmac *pdata = netdev_priv(ndev); + +- strncpy(drvinfo->driver, PHYTMAC_DRV_NAME, sizeof(drvinfo->driver)); + strncpy(drvinfo->version, PHYTMAC_DRIVER_VERSION, sizeof(drvinfo->version)); ++ strscpy(drvinfo->fw_version, pdata->fw_version, sizeof(drvinfo->fw_version)); + +- if (pdata->platdev) ++ if (pdata->platdev) { ++ strscpy(drvinfo->driver, PHYTMAC_PLAT_DRV_NAME, sizeof(drvinfo->driver)); + strncpy(drvinfo->bus_info, pdata->platdev->name, sizeof(drvinfo->bus_info)); +- else if (pdata->pcidev) ++ } else if (pdata->pcidev) { ++ strscpy(drvinfo->driver, PHYTMAC_PCI_DRV_NAME, sizeof(drvinfo->driver)); + strncpy(drvinfo->bus_info, pci_name(pdata->pcidev), sizeof(drvinfo->bus_info)); ++ } + } + + static const struct ethtool_ops phytmac_ethtool_ops = { +diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c +index 828bf3a83274..f97abb027aa6 100644 +--- a/drivers/net/ethernet/phytium/phytmac_main.c ++++ b/drivers/net/ethernet/phytium/phytmac_main.c +@@ -2,6 +2,8 @@ + /* + * Phytium Ethernet Controller driver + * ++ * Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. ++ * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +@@ -38,6 +40,8 @@ + #include + #include + #include ++#include ++#include + #include "phytmac.h" + #include "phytmac_ptp.h" + +@@ -58,11 +62,21 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + + /* Max length of transmit frame must be a multiple of 8 bytes */ + #define PHYTMAC_TX_LEN_ALIGN 8 +-/* Limit maximum TX length as per Cadence TSO errata. This is to avoid a ++/* Limit maximum TX length as per TSO errata. This is to avoid a + * false amba_error in TX path from the DMA assuming there is not enough + * space in the SRAM (16KB) even when there is. + */ + ++static int phytmac_xdp_xmit_back(struct phytmac *pdata, struct xdp_buff *xdp); ++ ++static inline int phytmac_calc_rx_buf_len(void) ++{ ++#if (PAGE_SIZE < 8192) ++ return rounddown(PHYTMAC_MAX_FRAME_BUILD_SKB, RX_BUFFER_MULTIPLE); ++#endif ++ return rounddown(PHYTMAC_RXBUFFER_2048, RX_BUFFER_MULTIPLE); ++} ++ + static int phytmac_queue_phyaddr_check(struct phytmac *pdata, dma_addr_t ring_base_addr, + int offset) + { +@@ -82,9 +96,20 @@ static int phytmac_queue_phyaddr_check(struct phytmac *pdata, dma_addr_t ring_ba + + static int phytmac_change_mtu(struct net_device *ndev, int new_mtu) + { ++ struct phytmac *pdata = netdev_priv(ndev); ++ int max_frame = new_mtu + PHYTMAC_ETH_PKT_HDR_PAD; ++ + if (netif_running(ndev)) + return -EBUSY; + ++ if (pdata->xdp_prog) { ++ if (max_frame > phytmac_calc_rx_buf_len()) { ++ netdev_warn(pdata->ndev, ++ "Requested MTU size is not supported with XDP.\n"); ++ return -EINVAL; ++ } ++ } ++ + if (new_mtu > MAX_MTU) { + netdev_info(ndev, "Can not set MTU over %d.\n", MAX_MTU); + return -EINVAL; +@@ -130,10 +155,12 @@ static int phytmac_get_mac_address(struct phytmac *pdata) + + if (is_valid_ether_addr(addr)) { + phytmac_hw_addr_set(pdata->ndev, addr); ++ ether_addr_copy(pdata->ndev->perm_addr, addr); + return 0; + } + dev_info(pdata->dev, "invalid hw address, using random\n"); + eth_hw_addr_random(pdata->ndev); ++ ether_addr_copy(pdata->ndev->perm_addr, pdata->ndev->dev_addr); + + return 0; + } +@@ -270,14 +297,6 @@ static struct net_device_stats *phytmac_get_stats(struct net_device *dev) + return nstat; + } + +-static inline int phytmac_calc_rx_buf_len(void) +-{ +-#if (PAGE_SIZE < 8192) +- return rounddown(PHYTMAC_MAX_FRAME_BUILD_SKB, RX_BUFFER_MULTIPLE); +-#endif +- return rounddown(PHYTMAC_RXBUFFER_2048, RX_BUFFER_MULTIPLE); +-} +- + struct phytmac_dma_desc *phytmac_get_rx_desc(struct phytmac_queue *queue, + unsigned int index) + { +@@ -345,6 +364,7 @@ static int phytmac_free_tx_resource(struct phytmac *pdata) + struct phytmac_dma_desc *tx_ring_base = NULL; + dma_addr_t tx_ring_base_addr; + unsigned int q; ++ int tx_offset; + int size; + + queue = pdata->queues; +@@ -362,8 +382,9 @@ static int phytmac_free_tx_resource(struct phytmac *pdata) + } + + if (tx_ring_base) { +- size = pdata->queues_num * (TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + +- RING_ADDR_INTERVAL); ++ tx_offset = TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + RING_ADDR_INTERVAL; ++ tx_offset = ALIGN(tx_offset, 4096); ++ size = pdata->queues_num * tx_offset; + dma_free_coherent(pdata->dev, size, tx_ring_base, tx_ring_base_addr); + } + +@@ -376,6 +397,7 @@ static int phytmac_free_rx_resource(struct phytmac *pdata) + struct phytmac_dma_desc *rx_ring_base = NULL; + dma_addr_t rx_ring_base_addr; + unsigned int q; ++ int rx_offset; + int size; + + queue = pdata->queues; +@@ -390,6 +412,11 @@ static int phytmac_free_rx_resource(struct phytmac *pdata) + if (queue->rx_ring) + queue->rx_ring = NULL; + ++ if (queue->xdp_prog) { ++ queue->xdp_prog = NULL; ++ xdp_rxq_info_unreg(&queue->xdp_rxq); ++ } ++ + if (queue->rx_buffer_info) { + vfree(queue->rx_buffer_info); + queue->rx_buffer_info = NULL; +@@ -397,8 +424,9 @@ static int phytmac_free_rx_resource(struct phytmac *pdata) + } + + if (rx_ring_base) { +- size = pdata->queues_num * (RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + +- RING_ADDR_INTERVAL); ++ rx_offset = RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + RING_ADDR_INTERVAL; ++ rx_offset = ALIGN(rx_offset, 4096); ++ size = pdata->queues_num * rx_offset; + dma_free_coherent(pdata->dev, size, rx_ring_base, rx_ring_base_addr); + } + +@@ -517,6 +545,20 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) + queue->rx_buffer_info = vzalloc(size); + if (!queue->rx_buffer_info) + goto err; ++ ++ memset(&queue->xdp_rxq, 0, sizeof(queue->xdp_rxq)); ++ WRITE_ONCE(queue->xdp_prog, pdata->xdp_prog); ++ ++ /* XDP RX-queue info */ ++ ret = xdp_rxq_info_reg(&queue->xdp_rxq, queue->pdata->ndev, q); ++ if (ret < 0) { ++ netdev_err(pdata->ndev, "Failed to register xdp_rxq index %u\n", q); ++ goto err; ++ } ++ ++ xdp_rxq_info_unreg_mem_model(&queue->xdp_rxq); ++ WARN_ON(xdp_rxq_info_reg_mem_model(&queue->xdp_rxq, ++ MEM_TYPE_PAGE_SHARED, NULL)); + } + + return 0; +@@ -837,6 +879,114 @@ static struct sk_buff *phytmac_build_skb(struct phytmac_rx_buffer *rx_buffer, + return skb; + } + ++static void phytmac_rx_buffer_flip(struct phytmac_rx_buffer *rx_buffer, unsigned int size) ++{ ++ unsigned int truesize; ++ ++#if (PAGE_SIZE < 8192) ++ truesize = PHYTMAC_RX_PAGE_SIZE / 2; ++ rx_buffer->page_offset ^= truesize; ++#else ++ truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + ++ SKB_DATA_ALIGN(PHYTMAC_SKB_PAD + size); ++ rx_buffer->page_offset += truesize; ++#endif ++} ++ ++static struct sk_buff *phytmac_run_xdp(struct phytmac *pdata, ++ struct xdp_buff *xdp) ++{ ++ int err, result = PHYTMAC_XDP_PASS; ++ struct bpf_prog *xdp_prog; ++ u32 act; ++ ++ rcu_read_lock(); ++ xdp_prog = READ_ONCE(pdata->xdp_prog); ++ ++ if (!xdp_prog) ++ goto xdp_out; ++ ++ prefetchw(xdp->data_hard_start); /* xdp_frame write */ ++ ++ act = bpf_prog_run_xdp(xdp_prog, xdp); ++ switch (act) { ++ case XDP_PASS: ++ break; ++ case XDP_TX: ++ result = phytmac_xdp_xmit_back(pdata, xdp); ++ if (result == PHYTMAC_XDP_CONSUMED) ++ goto out_failure; ++ break; ++ case XDP_REDIRECT: ++ err = xdp_do_redirect(pdata->ndev, xdp, xdp_prog); ++ if (err) ++ goto out_failure; ++ result = PHYTMAC_XDP_REDIR; ++ break; ++ default: ++ bpf_warn_invalid_xdp_action(act); ++ fallthrough; ++ case XDP_ABORTED: ++out_failure: ++ trace_xdp_exception(pdata->ndev, xdp_prog, act); ++ fallthrough; ++ case XDP_DROP: ++ result = PHYTMAC_XDP_CONSUMED; ++ break; ++ } ++xdp_out: ++ rcu_read_unlock(); ++ return ERR_PTR(-result); ++} ++ ++static struct sk_buff *phytmac_rx_xdp_single(struct phytmac_queue *queue, ++ struct phytmac_dma_desc *desc, ++ unsigned int *xdp_xmit) ++{ ++ struct phytmac *pdata = queue->pdata; ++ struct phytmac_hw_if *hw_if = pdata->hw_if; ++ struct phytmac_rx_buffer *rx_buffer; ++ struct sk_buff *skb = NULL; ++ unsigned int len; ++ struct xdp_buff xdp; ++ ++ xdp.rxq = &queue->xdp_rxq; ++ ++ len = hw_if->get_rx_pkt_len(pdata, desc); ++ rx_buffer = phytmac_get_rx_buffer(queue, queue->rx_tail, len); ++ ++ xdp.data = page_address(rx_buffer->page) + rx_buffer->page_offset; ++ xdp.data_meta = xdp.data; ++ xdp.data_hard_start = xdp.data - PHYTMAC_SKB_PAD; ++ xdp.data_end = xdp.data + len; ++#if (PAGE_SIZE < 8192) ++ xdp.frame_sz = PHYTMAC_RX_PAGE_SIZE / 2; ++#else ++ xdp.frame_sz = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + ++ SKB_DATA_ALIGN(PHYTMAC_SKB_PAD + len); ++#endif ++ skb = phytmac_run_xdp(pdata, &xdp); ++ ++ if (IS_ERR(skb)) { ++ unsigned int xdp_res = -PTR_ERR(skb); ++ ++ if (xdp_res & (PHYTMAC_XDP_TX | PHYTMAC_XDP_REDIR)) { ++ *xdp_xmit |= xdp_res; ++ phytmac_rx_buffer_flip(rx_buffer, len); ++ } else { ++ rx_buffer->pagecnt_bias++; ++ } ++ hw_if->zero_rx_desc_addr(desc); ++ phytmac_put_rx_buffer(queue, rx_buffer); ++ pdata->ndev->stats.rx_bytes += len; ++ queue->stats.rx_bytes += len; ++ } else { ++ rx_buffer->pagecnt_bias++; ++ } ++ ++ return skb; ++} ++ + static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phytmac_dma_desc *desc) + { + struct phytmac *pdata = queue->pdata; +@@ -847,7 +997,6 @@ static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phy + + len = hw_if->get_rx_pkt_len(pdata, desc); + rx_buffer = phytmac_get_rx_buffer(queue, queue->rx_tail, len); +- hw_if->zero_rx_desc_addr(desc); + + skb = phytmac_build_skb(rx_buffer, len); + if (unlikely(!skb)) { +@@ -859,6 +1008,7 @@ static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phy + return NULL; + } + ++ hw_if->zero_rx_desc_addr(desc); + phytmac_put_rx_buffer(queue, rx_buffer); + + skb->protocol = eth_type_trans(skb, pdata->ndev); +@@ -894,7 +1044,6 @@ static struct sk_buff *phytmac_rx_frame(struct phytmac_queue *queue, + + desc = phytmac_get_rx_desc(queue, first_frag); + rx_buffer = phytmac_get_rx_buffer(queue, first_frag, frag_len); +- hw_if->zero_rx_desc_addr(desc); + + skb = phytmac_build_skb(rx_buffer, frag_len); + if (unlikely(!skb)) { +@@ -905,6 +1054,7 @@ static struct sk_buff *phytmac_rx_frame(struct phytmac_queue *queue, + return NULL; + } + ++ hw_if->zero_rx_desc_addr(desc); + phytmac_put_rx_buffer(queue, rx_buffer); + + for (frag = first_frag + 1; ; frag++) { +@@ -1011,6 +1161,7 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) + queue->rx_next_to_alloc = queue->rx_head; + /* make newly descriptor to hardware */ + wmb(); ++ hw_if->update_rx_tail(queue); + } + + static int phytmac_rx(struct phytmac_queue *queue, struct napi_struct *napi, +@@ -1020,6 +1171,7 @@ static int phytmac_rx(struct phytmac_queue *queue, struct napi_struct *napi, + struct phytmac_hw_if *hw_if = pdata->hw_if; + struct sk_buff *skb; + struct phytmac_dma_desc *desc; ++ unsigned int xdp_xmit = 0; + int count = 0; + + while (count < budget) { +@@ -1032,10 +1184,15 @@ static int phytmac_rx(struct phytmac_queue *queue, struct napi_struct *napi, + /* Ensure ctrl is at least as up-to-date as rxused */ + dma_rmb(); + +- if (hw_if->rx_single_buffer(desc)) +- skb = phytmac_rx_single(queue, desc); +- else ++ if (hw_if->rx_single_buffer(desc)) { ++ skb = phytmac_rx_xdp_single(queue, desc, &xdp_xmit); ++ if (!IS_ERR(skb)) ++ skb = phytmac_rx_single(queue, desc); ++ } else { ++ if (pdata->xdp_prog) ++ netdev_warn(pdata->ndev, "xdp does not support multiple buffers!!\n"); + skb = phytmac_rx_mbuffer(queue); ++ } + + if (!skb) { + netdev_warn(pdata->ndev, "phytmac rx skb is NULL\n"); +@@ -1044,18 +1201,28 @@ static int phytmac_rx(struct phytmac_queue *queue, struct napi_struct *napi, + + pdata->ndev->stats.rx_packets++; + queue->stats.rx_packets++; +- pdata->ndev->stats.rx_bytes += skb->len; +- queue->stats.rx_bytes += skb->len; ++ if (!IS_ERR(skb)) { ++ pdata->ndev->stats.rx_bytes += skb->len; ++ queue->stats.rx_bytes += skb->len; ++ } + queue->rx_tail = (queue->rx_tail + 1) & (pdata->rx_ring_size - 1); + + count++; + ++ if (IS_ERR(skb)) { ++ skb = NULL; ++ continue; ++ } ++ + if (IS_REACHABLE(CONFIG_PHYTMAC_ENABLE_PTP)) + phytmac_ptp_rxstamp(pdata, skb, desc); + + napi_gro_receive(napi, skb); + } + ++ if (xdp_xmit & PHYTMAC_XDP_REDIR) ++ xdp_do_flush_map(); ++ + phytmac_rx_clean(queue); + + return count; +@@ -1073,8 +1240,13 @@ static void phytmac_tx_unmap(struct phytmac *pdata, struct phytmac_tx_skb *tx_sk + tx_skb->addr = 0; + } + +- if (tx_skb->skb) { +- napi_consume_skb(tx_skb->skb, budget); ++ if (tx_skb->type == PHYTMAC_TYPE_XDP) { ++ if (tx_skb->xdpf) ++ xdp_return_frame(tx_skb->xdpf); ++ tx_skb->xdpf = NULL; ++ } else { ++ if (tx_skb->skb) ++ napi_consume_skb(tx_skb->skb, budget); + tx_skb->skb = NULL; + } + } +@@ -1108,6 +1280,19 @@ static int phytmac_maybe_wake_tx_queue(struct phytmac_queue *queue) + return (space <= (3 * pdata->tx_ring_size / 4)) ? 1 : 0; + } + ++static inline void phytmac_do_ptp_txstamp(struct phytmac_queue *queue, ++ struct sk_buff *skb, ++ struct phytmac_dma_desc *desc) ++{ ++ if (IS_REACHABLE(CONFIG_PHYTMAC_ENABLE_PTP)) { ++ if (unlikely(skb_shinfo(skb)->tx_flags & ++ SKBTX_HW_TSTAMP) && ++ !phytmac_ptp_one_step(skb)) { ++ phytmac_ptp_txstamp(queue, skb, desc); ++ } ++ } ++} ++ + static int phytmac_tx_clean(struct phytmac_queue *queue, int budget) + { + struct phytmac *pdata = queue->pdata; +@@ -1120,7 +1305,7 @@ static int phytmac_tx_clean(struct phytmac_queue *queue, int budget) + unsigned int tail = queue->tx_tail; + unsigned int head; + +- spin_lock(&pdata->lock); ++ spin_lock(&queue->tx_lock); + + for (head = queue->tx_head; head != tail && packet_count < budget; ) { + struct sk_buff *skb; +@@ -1135,29 +1320,34 @@ static int phytmac_tx_clean(struct phytmac_queue *queue, int budget) + /* Process all buffers of the current transmitted frame */ + for (;; head++) { + tx_skb = phytmac_get_tx_skb(queue, head); +- skb = tx_skb->skb; +- if (skb) { +- complete = 1; +- if (IS_REACHABLE(CONFIG_PHYTMAC_ENABLE_PTP)) { +- if (unlikely(skb_shinfo(skb)->tx_flags & +- SKBTX_HW_TSTAMP) && +- !phytmac_ptp_one_step(skb)) { +- phytmac_ptp_txstamp(queue, skb, desc); +- } ++ if (tx_skb->type == PHYTMAC_TYPE_SKB) { ++ skb = tx_skb->skb; ++ if (skb) { ++ complete = 1; ++ phytmac_do_ptp_txstamp(queue, skb, desc); ++ ++ if (netif_msg_drv(pdata)) ++ netdev_info(pdata->ndev, "desc %u (data %p) tx complete\n", ++ head, tx_skb->skb->data); ++ ++ pdata->ndev->stats.tx_packets++; ++ queue->stats.tx_packets++; ++ pdata->ndev->stats.tx_bytes += tx_skb->skb->len; ++ queue->stats.tx_bytes += tx_skb->skb->len; ++ packet_count++; ++ } ++ } else if (tx_skb->type == PHYTMAC_TYPE_XDP) { ++ if (tx_skb->xdpf) { ++ complete = 1; ++ pdata->ndev->stats.tx_packets++; ++ queue->stats.tx_packets++; ++ pdata->ndev->stats.tx_bytes += tx_skb->xdpf->len; ++ queue->stats.tx_bytes += tx_skb->xdpf->len; ++ packet_count++; + } +- +- if (netif_msg_drv(pdata)) +- netdev_info(pdata->ndev, "desc %u (data %p) tx complete\n", +- head, tx_skb->skb->data); +- +- pdata->ndev->stats.tx_packets++; +- queue->stats.tx_packets++; +- pdata->ndev->stats.tx_bytes += tx_skb->skb->len; +- queue->stats.tx_bytes += tx_skb->skb->len; +- packet_count++; + } + +- /* Now we can safely release resources */ ++ /* Now we can safely release resources */ + phytmac_tx_unmap(pdata, tx_skb, budget); + + if (complete) { +@@ -1175,7 +1365,7 @@ static int phytmac_tx_clean(struct phytmac_queue *queue, int budget) + if (__netif_subqueue_stopped(pdata->ndev, queue_index) && + (phytmac_maybe_wake_tx_queue(queue))) + netif_wake_subqueue(pdata->ndev, queue_index); +- spin_unlock(&pdata->lock); ++ spin_unlock(&queue->tx_lock); + + return packet_count; + } +@@ -1258,6 +1448,7 @@ static inline int phytmac_clear_csum(struct sk_buff *skb) + + static int phytmac_add_fcs(struct sk_buff **skb, struct net_device *ndev) + { ++#ifdef PHYTMAC_SW_FCS + bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) || + skb_is_nonlinear(*skb); + int padlen = ETH_ZLEN - (*skb)->len; +@@ -1267,7 +1458,7 @@ static int phytmac_add_fcs(struct sk_buff **skb, struct net_device *ndev) + u32 fcs; + int i; + +- if ((ndev->features & NETIF_F_HW_CSUM) || ++ if (!(ndev->features & NETIF_F_HW_CSUM) || + !((*skb)->ip_summed != CHECKSUM_PARTIAL) || + skb_shinfo(*skb)->gso_size || phytmac_ptp_one_step(*skb)) + return 0; +@@ -1304,6 +1495,8 @@ static int phytmac_add_fcs(struct sk_buff **skb, struct net_device *ndev) + + for (i = 0; i < 4; ++i) + skb_put_u8(*skb, (fcs >> (i * 8)) & 0xff); ++#endif ++ + return 0; + } + +@@ -1353,13 +1546,13 @@ static int phytmac_packet_info(struct phytmac *pdata, + desc_cnt += TXD_USE_COUNT(pdata, skb_frag_size(&skb_shinfo(skb)->frags[f])); + packet->desc_cnt = desc_cnt; + +- if ((!(pdata->ndev->features & NETIF_F_HW_CSUM)) && ++#ifdef PHYTMAC_SW_FCS ++ if ((pdata->ndev->features & NETIF_F_HW_CSUM) && + skb->ip_summed != CHECKSUM_PARTIAL && + !is_lso && + !phytmac_ptp_one_step(skb)) + packet->nocrc = 1; +- else +- packet->nocrc = 0; ++#endif + + if (netif_msg_pktdata(pdata)) { + netdev_info(pdata->ndev, "packet info: desc_cnt=%d, nocrc=%d,ip_summed=%d\n", +@@ -1399,6 +1592,7 @@ static unsigned int phytmac_tx_map(struct phytmac *pdata, + + /* Save info to properly release resources */ + tx_skb->skb = NULL; ++ tx_skb->type = PHYTMAC_TYPE_SKB; + tx_skb->addr = mapping; + tx_skb->length = size; + tx_skb->mapped_as_page = false; +@@ -1427,6 +1621,7 @@ static unsigned int phytmac_tx_map(struct phytmac *pdata, + + /* Save info to properly release resources */ + tx_skb->skb = NULL; ++ tx_skb->type = PHYTMAC_TYPE_SKB; + tx_skb->addr = mapping; + tx_skb->length = size; + tx_skb->mapped_as_page = true; +@@ -1491,6 +1686,59 @@ static inline void phytmac_init_ring(struct phytmac *pdata) + hw_if->init_ring_hw(pdata); + } + ++static int phytmac_start_xmit_xdp(struct phytmac *pdata, ++ struct phytmac_queue *queue, ++ struct xdp_frame *xdpf) ++{ ++ u32 len; ++ struct phytmac_tx_skb *tx_buffer; ++ struct packet_info packet; ++ dma_addr_t dma; ++ struct phytmac_hw_if *hw_if = pdata->hw_if; ++ u16 tx_tail; ++ ++ len = xdpf->len; ++ ++ memset(&packet, 0, sizeof(struct packet_info)); ++ ++ if (unlikely(!phytmac_txdesc_unused(queue))) ++ return PHYTMAC_XDP_CONSUMED; ++ ++ dma = dma_map_single(pdata->dev, xdpf->data, len, DMA_TO_DEVICE); ++ if (dma_mapping_error(pdata->dev, dma)) ++ return PHYTMAC_XDP_CONSUMED; ++ ++ /* record the location of the first descriptor for this packet */ ++ tx_buffer = phytmac_get_tx_skb(queue, queue->tx_tail); ++ tx_buffer->mapped_as_page = false; ++ ++ /* Temporarily set the tail pointer for the next package */ ++ tx_tail = queue->tx_tail + 1; ++ ++ dma_unmap_len_set(tx_buffer, length, len); ++ dma_unmap_addr_set(tx_buffer, addr, dma); ++ tx_buffer->type = PHYTMAC_TYPE_XDP; ++ tx_buffer->xdpf = xdpf; ++ ++ packet.lso = 0; ++ packet.mss = 0; ++ packet.nocrc = 0; ++ ++ /* Avoid any potential race with xdp_xmit and cleanup */ ++ smp_wmb(); ++ ++ hw_if->tx_map(queue, tx_tail, &packet); ++ ++ queue->tx_tail = tx_tail & (pdata->tx_ring_size - 1); ++ ++ hw_if->transmit(queue); ++ ++ /* Make sure there is space in the ring for the next send. */ ++ phytmac_maybe_stop_tx_queue(queue, PHYTMAC_DESC_NEEDED); ++ ++ return PHYTMAC_XDP_TX; ++} ++ + static netdev_tx_t phytmac_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct phytmac *pdata = netdev_priv(ndev); +@@ -1499,7 +1747,6 @@ static netdev_tx_t phytmac_start_xmit(struct sk_buff *skb, struct net_device *nd + struct phytmac_queue *queue = &pdata->queues[queue_index]; + netdev_tx_t ret = NETDEV_TX_OK; + struct packet_info packet; +- unsigned long flags; + + if (phytmac_clear_csum(skb)) { + dev_kfree_skb_any(skb); +@@ -1520,7 +1767,7 @@ static netdev_tx_t phytmac_start_xmit(struct sk_buff *skb, struct net_device *nd + if (netif_msg_pktdata(pdata)) + phytmac_dump_pkt(pdata, skb, true); + +- spin_lock_irqsave(&pdata->lock, flags); ++ spin_lock_bh(&queue->tx_lock); + /* Check that there are enough descriptors available */ + ret = phytmac_maybe_stop_tx_queue(queue, packet.desc_cnt); + if (ret) +@@ -1539,7 +1786,7 @@ static netdev_tx_t phytmac_start_xmit(struct sk_buff *skb, struct net_device *nd + hw_if->transmit(queue); + + tx_return: +- spin_unlock_irqrestore(&pdata->lock, flags); ++ spin_unlock_bh(&queue->tx_lock); + return ret; + } + +@@ -1685,6 +1932,7 @@ static void phytmac_mac_link_down(struct phylink_config *config, unsigned int mo + unsigned int q; + unsigned long flags; + struct phytmac_tx_skb *tx_skb; ++ struct phytmac_dma_desc *tx_desc = NULL; + int i; + + if (netif_msg_link(pdata)) { +@@ -1703,18 +1951,22 @@ static void phytmac_mac_link_down(struct phylink_config *config, unsigned int mo + + /* Disable Rx and Tx */ + hw_if->enable_network(pdata, false, PHYTMAC_RX | PHYTMAC_TX); ++ spin_unlock_irqrestore(&pdata->lock, flags); + + /* Tx clean */ + for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) { ++ spin_lock_bh(&queue->tx_lock); + for (i = 0; i < pdata->tx_ring_size; i++) { + tx_skb = phytmac_get_tx_skb(queue, i); + if (tx_skb) + phytmac_tx_unmap(pdata, tx_skb, 0); ++ ++ tx_desc = phytmac_get_tx_desc(queue, i); ++ hw_if->zero_tx_desc(tx_desc); + } ++ spin_unlock_bh(&queue->tx_lock); + } + +- spin_unlock_irqrestore(&pdata->lock, flags); +- + netif_tx_stop_all_queues(ndev); + } + +@@ -1777,6 +2029,12 @@ int phytmac_mdio_register(struct phytmac *pdata) + goto err_out; + } + ++ if (hw_if->mdio_idle) { ++ ret = hw_if->mdio_idle(pdata); ++ if (ret) ++ goto free_mdio; ++ } ++ + pdata->mii_bus->name = "phytmac_mii_bus"; + pdata->mii_bus->read = &phytmac_mdio_read; + pdata->mii_bus->write = &phytmac_mdio_write; +@@ -1927,10 +2185,6 @@ static int phytmac_open(struct net_device *ndev) + if (netif_msg_probe(pdata)) + dev_dbg(pdata->dev, "open\n"); + +- /* phytmac_powerup */ +- if (pdata->power_state == PHYTMAC_POWEROFF) +- hw_if->poweron(pdata, PHYTMAC_POWERON); +- + if (hw_if->init_msg_ring) + hw_if->init_msg_ring(pdata); + +@@ -2037,10 +2291,6 @@ static int phytmac_close(struct net_device *ndev) + if (IS_REACHABLE(CONFIG_PHYTMAC_ENABLE_PTP)) + phytmac_ptp_unregister(pdata); + +- /* phytmac_powerup */ +- if (pdata->power_state == PHYTMAC_POWERON) +- hw_if->poweron(pdata, PHYTMAC_POWEROFF); +- + return 0; + } + +@@ -2178,6 +2428,136 @@ int phytmac_reset_ringsize(struct phytmac *pdata, u32 rx_size, u32 tx_size) + return ret; + } + ++static int phytmac_xdp_setup(struct net_device *dev, struct bpf_prog *prog) ++{ ++ int i, frame_size = dev->mtu + PHYTMAC_ETH_PKT_HDR_PAD; ++ struct phytmac *pdata = netdev_priv(dev); ++ struct bpf_prog *old_prog; ++ bool running = netif_running(dev); ++ bool need_reset; ++ ++ /* verify phytmac rx ring attributes are sufficient for XDP */ ++ if (frame_size > phytmac_calc_rx_buf_len()) { ++ netdev_warn(dev, "XDP RX buffer size %d is too small for the frame size %d\n", ++ phytmac_calc_rx_buf_len(), frame_size); ++ return -EINVAL; ++ } ++ ++ old_prog = xchg(&pdata->xdp_prog, prog); ++ need_reset = (!!prog != !!old_prog); ++ ++ /* device is up and bpf is added/removed, must setup the RX queues */ ++ if (need_reset && running) { ++ phytmac_close(dev); ++ } else { ++ for (i = 0; i < pdata->queues_num; i++) ++ (void)xchg(&pdata->queues[i].xdp_prog, ++ pdata->xdp_prog); ++ } ++ ++ if (old_prog) ++ bpf_prog_put(old_prog); ++ ++ /* bpf is just replaced, RXQ and MTU are already setup */ ++ if (!need_reset) ++ return 0; ++ ++ if (running) ++ phytmac_open(dev); ++ ++ return 0; ++} ++ ++static int phytmac_xdp(struct net_device *dev, struct netdev_bpf *xdp) ++{ ++ switch (xdp->command) { ++ case XDP_SETUP_PROG: ++ return phytmac_xdp_setup(dev, xdp->prog); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static struct phytmac_queue *phytmac_xdp_txq_mapping(struct phytmac *pdata) ++{ ++ unsigned int r_idx = smp_processor_id(); ++ ++ if (r_idx >= pdata->queues_num) ++ r_idx = r_idx % pdata->queues_num; ++ ++ return &pdata->queues[r_idx]; ++} ++ ++static int phytmac_xdp_xmit_back(struct phytmac *pdata, struct xdp_buff *xdp) ++{ ++ struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); ++ int cpu = smp_processor_id(); ++ struct phytmac_queue *queue; ++ struct netdev_queue *nq; ++ u32 ret; ++ ++ if (unlikely(!xdpf)) ++ return PHYTMAC_XDP_CONSUMED; ++ ++ /* During program transitions its possible adapter->xdp_prog is assigned ++ * but ring has not been configured yet. In this case simply abort xmit. ++ */ ++ queue = pdata->xdp_prog ? phytmac_xdp_txq_mapping(pdata) : NULL; ++ if (unlikely(!queue)) ++ return PHYTMAC_XDP_CONSUMED; ++ ++ nq = phytmac_get_txq(pdata, queue); ++ __netif_tx_lock(nq, cpu); ++ /* Avoid transmit queue timeout since we share it with the slow path */ ++ nq->trans_start = jiffies; ++ ret = phytmac_start_xmit_xdp(pdata, queue, xdpf); ++ __netif_tx_unlock(nq); ++ ++ return ret; ++} ++ ++static int phytmac_xdp_xmit(struct net_device *dev, int n, ++ struct xdp_frame **frames, u32 flags) ++{ ++ struct phytmac *pdata = netdev_priv(dev); ++ int cpu = smp_processor_id(); ++ struct phytmac_queue *queue; ++ struct netdev_queue *nq; ++ int drops = 0; ++ int i; ++ ++ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) ++ return -EINVAL; ++ ++ /* During program transitions its possible pdata->xdp_prog is assigned ++ * but ring has not been configured yet. In this case simply abort xmit. ++ */ ++ queue = pdata->xdp_prog ? phytmac_xdp_txq_mapping(pdata) : NULL; ++ if (unlikely(!queue)) ++ return -ENXIO; ++ ++ nq = phytmac_get_txq(pdata, queue); ++ __netif_tx_lock(nq, cpu); ++ ++ /* Avoid transmit queue timeout since we share it with the slow path */ ++ nq->trans_start = jiffies; ++ ++ for (i = 0; i < n; i++) { ++ struct xdp_frame *xdpf = frames[i]; ++ int err; ++ ++ err = phytmac_start_xmit_xdp(pdata, queue, xdpf); ++ if (err != PHYTMAC_XDP_TX) { ++ xdp_return_frame_rx_napi(xdpf); ++ drops++; ++ } ++ } ++ ++ __netif_tx_unlock(nq); ++ ++ return n - drops; ++} ++ + static const struct net_device_ops phytmac_netdev_ops = { + .ndo_open = phytmac_open, + .ndo_stop = phytmac_close, +@@ -2192,6 +2572,8 @@ static const struct net_device_ops phytmac_netdev_ops = { + .ndo_features_check = phytmac_features_check, + .ndo_vlan_rx_add_vid = ncsi_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = ncsi_vlan_rx_kill_vid, ++ .ndo_bpf = phytmac_xdp, ++ .ndo_xdp_xmit = phytmac_xdp_xmit, + }; + + static int phytmac_init(struct phytmac *pdata) +@@ -2298,6 +2680,16 @@ void phytmac_default_config(struct phytmac *pdata) + ndev->max_mtu = ETH_DATA_LEN; + + ndev->features = ndev->hw_features; ++ ++ switch (pdata->version) { ++ case VERSION_V3: ++ strscpy(pdata->fw_version, "MAC_FTM300", sizeof(pdata->fw_version)); ++ break; ++ ++ default: ++ strscpy(pdata->fw_version, "", sizeof(pdata->fw_version)); ++ break; ++ } + } + + static void phytmac_ncsi_handler(struct ncsi_dev *nd) +@@ -2313,6 +2705,7 @@ int phytmac_drv_probe(struct phytmac *pdata) + { + struct net_device *ndev = pdata->ndev; + struct device *dev = pdata->dev; ++ struct phytmac_hw_if *hw_if = pdata->hw_if; + int ret = 0; + + if (netif_msg_probe(pdata)) +@@ -2336,12 +2729,11 @@ int phytmac_drv_probe(struct phytmac *pdata) + goto err_out; + } + +- netif_carrier_off(ndev); +- ret = register_netdev(ndev); +- if (ret) { +- dev_err(pdata->dev, "Cannot register net device, aborting.\n"); +- goto err_out; +- } ++ if (pdata->power_state == PHYTMAC_POWEROFF) ++ hw_if->poweron(pdata, PHYTMAC_POWERON); ++ ++ if (hw_if->init_msg_ring) ++ hw_if->init_msg_ring(pdata); + + if (pdata->use_mii && !pdata->mii_bus) { + ret = phytmac_mdio_register(pdata); +@@ -2363,6 +2755,13 @@ int phytmac_drv_probe(struct phytmac *pdata) + goto err_phylink_init; + } + ++ ret = register_netdev(ndev); ++ if (ret) { ++ dev_err(pdata->dev, "Cannot register net device, aborting.\n"); ++ goto err_phylink_init; ++ } ++ netif_carrier_off(ndev); ++ + if (netif_msg_probe(pdata)) + dev_dbg(pdata->dev, "probe successfully! Phytium %s at 0x%08lx irq %d (%pM)\n", + "MAC", ndev->base_addr, ndev->irq, ndev->dev_addr); +@@ -2377,8 +2776,6 @@ int phytmac_drv_probe(struct phytmac *pdata) + if (pdata->mii_bus) + mdiobus_free(pdata->mii_bus); + +- unregister_netdev(ndev); +- + err_out: + return ret; + } +@@ -2387,12 +2784,15 @@ EXPORT_SYMBOL_GPL(phytmac_drv_probe); + int phytmac_drv_remove(struct phytmac *pdata) + { + struct net_device *ndev = pdata->ndev; ++ struct phytmac_hw_if *hw_if = pdata->hw_if; + + if (ndev) { + if (pdata->use_ncsi && pdata->ncsidev) + ncsi_unregister_dev(pdata->ncsidev); + + unregister_netdev(ndev); ++ if (pdata->power_state == PHYTMAC_POWERON) ++ hw_if->poweron(pdata, PHYTMAC_POWEROFF); + + if (pdata->use_mii && pdata->mii_bus) { + mdiobus_unregister(pdata->mii_bus); +@@ -2426,12 +2826,15 @@ int phytmac_drv_suspend(struct phytmac *pdata) + /* napi_disable */ + for (q = 0, queue = pdata->queues; q < pdata->queues_num; + ++q, ++queue) { ++ hw_if->disable_irq(pdata, queue->index, pdata->rx_irq_mask | pdata->tx_irq_mask); ++ hw_if->clear_irq(pdata, queue->index, pdata->rx_irq_mask | pdata->tx_irq_mask); + napi_disable(&queue->tx_napi); + napi_disable(&queue->rx_napi); + } + + if (pdata->wol) { + hw_if->set_wol(pdata, pdata->wol); ++ pdata->power_state = PHYTMAC_POWEROFF; + } else { + rtnl_lock(); + phylink_stop(pdata->phylink); +@@ -2453,15 +2856,14 @@ int phytmac_drv_resume(struct phytmac *pdata) + struct phytmac_hw_if *hw_if = pdata->hw_if; + struct ethtool_rx_fs_item *item; + +- if (!netif_running(pdata->ndev)) +- return 0; +- +- if (pdata->power_state == PHYTMAC_POWEROFF) +- hw_if->poweron(pdata, PHYTMAC_POWERON); ++ hw_if->poweron(pdata, PHYTMAC_POWERON); + + if (hw_if->init_msg_ring) + hw_if->init_msg_ring(pdata); + ++ if (!netif_running(pdata->ndev)) ++ return 0; ++ + if (pdata->wol) { + hw_if->set_wol(pdata, 0); + rtnl_lock(); +@@ -2508,7 +2910,7 @@ struct phytmac *phytmac_alloc_pdata(struct device *dev) + pdata->dev = dev; + + spin_lock_init(&pdata->lock); +- spin_lock_init(&pdata->msg_lock); ++ spin_lock_init(&pdata->msg_ring.msg_lock); + spin_lock_init(&pdata->ts_clk_lock); + pdata->msg_enable = netif_msg_init(debug, PHYTMAC_DEFAULT_MSG_ENABLE); + +@@ -2524,6 +2926,88 @@ void phytmac_free_pdata(struct phytmac *pdata) + } + EXPORT_SYMBOL_GPL(phytmac_free_pdata); + ++void phytmac_drv_shutdown(struct phytmac *pdata) ++{ ++ struct net_device *netdev = pdata->ndev; ++ struct phytmac_hw_if *hw_if = pdata->hw_if; ++ ++ rtnl_lock(); ++ netif_device_detach(netdev); ++ ++ if (netif_running(netdev)) ++ phytmac_close(netdev); ++ rtnl_unlock(); ++ ++ if (pdata->power_state == PHYTMAC_POWERON) ++ hw_if->poweron(pdata, PHYTMAC_POWEROFF); ++} ++EXPORT_SYMBOL_GPL(phytmac_drv_shutdown); ++ ++static void phytmac_devm_iounmap_np(struct device *dev, void *res) ++{ ++ iounmap(*(void __iomem **)res); ++} ++ ++static void __iomem *phytmac_devm_ioremap_np(struct device *dev, resource_size_t offset, ++ resource_size_t size) ++{ ++ void __iomem **ptr, *addr = NULL; ++ ++ ptr = devres_alloc_node(phytmac_devm_iounmap_np, sizeof(*ptr), GFP_KERNEL, ++ dev_to_node(dev)); ++ if (!ptr) ++ return NULL; ++ ++ addr = phytmac_ioremap_np(offset, size); ++ if (addr) { ++ *ptr = addr; ++ devres_add(dev, ptr); ++ } else ++ devres_free(ptr); ++ ++ return addr; ++} ++ ++void __iomem * ++phytmac_devm_ioremap_resource_np(struct device *dev, const struct resource *res) ++{ ++ resource_size_t size; ++ void __iomem *dest_ptr; ++ char *pretty_name; ++ ++ if (!res || resource_type(res) != IORESOURCE_MEM) { ++ dev_err(dev, "invalid resource %pR\n", res); ++ return IOMEM_ERR_PTR(-EINVAL); ++ } ++ ++ size = resource_size(res); ++ ++ if (res->name) ++ pretty_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", ++ dev_name(dev), res->name); ++ else ++ pretty_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); ++ if (!pretty_name) { ++ dev_err(dev, "can't generate pretty name for resource %pR\n", res); ++ return IOMEM_ERR_PTR(-ENOMEM); ++ } ++ ++ if (!devm_request_mem_region(dev, res->start, size, pretty_name)) { ++ dev_err(dev, "can't request region for resource %pR\n", res); ++ return IOMEM_ERR_PTR(-EBUSY); ++ } ++ ++ dest_ptr = phytmac_devm_ioremap_np(dev, res->start, size); ++ if (!dest_ptr) { ++ dev_err(dev, "ioremap failed for resource %pR\n", res); ++ devm_release_mem_region(dev, res->start, size); ++ dest_ptr = IOMEM_ERR_PTR(-ENOMEM); ++ } ++ ++ return dest_ptr; ++} ++EXPORT_SYMBOL_GPL(phytmac_devm_ioremap_resource_np); ++ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Phytium Ethernet driver"); + MODULE_AUTHOR("Wenting Song"); +diff --git a/drivers/net/ethernet/phytium/phytmac_pci.c b/drivers/net/ethernet/phytium/phytmac_pci.c +index cc0cbae28431..fac5d717ad76 100644 +--- a/drivers/net/ethernet/phytium/phytmac_pci.c ++++ b/drivers/net/ethernet/phytium/phytmac_pci.c +@@ -1,6 +1,10 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Phytium GMAC PCI wrapper. ++ * ++ * Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. ++ * ++ * Author: Wenting Song + */ + + #include +@@ -20,7 +24,6 @@ + struct phytmac_data { + struct phytmac_hw_if *hw_if; + u32 caps; +- u32 tsu_rate; + u16 queue_num; + int speed; + bool duplex; +@@ -38,10 +41,10 @@ static const u32 fixedlink[][5] = { + }; + + static const struct property_entry fl_properties[][2] = { +- {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[0]), {}}, +- {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[1]), {}}, +- {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[2]), {}}, +- {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[3]), {}}, ++ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[0]), {} }, ++ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[1]), {} }, ++ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[2]), {} }, ++ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[3]), {} }, + }; + + static int phytmac_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +@@ -71,7 +74,7 @@ static int phytmac_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i + + /* Obtain the mmio areas for the device */ + bar_mask = pci_select_bars(pdev, IORESOURCE_MEM); +- ret = pcim_iomap_regions(pdev, bar_mask, PHYTMAC_DRV_NAME); ++ ret = pcim_iomap_regions(pdev, bar_mask, PHYTMAC_PCI_DRV_NAME); + if (ret) { + dev_err(dev, "pcim_iomap_regions failed\n"); + goto err_pci_enable; +@@ -302,7 +305,7 @@ static const struct dev_pm_ops phytmac_pci_pm_ops = { + }; + + static struct pci_driver phytmac_driver = { +- .name = PHYTMAC_DRV_NAME, ++ .name = PHYTMAC_PCI_DRV_NAME, + .id_table = phytmac_pci_table, + .probe = phytmac_pci_probe, + .remove = phytmac_pci_remove, +diff --git a/drivers/net/ethernet/phytium/phytmac_platform.c b/drivers/net/ethernet/phytium/phytmac_platform.c +index 5033e03ac2dd..2f2170cf0775 100644 +--- a/drivers/net/ethernet/phytium/phytmac_platform.c ++++ b/drivers/net/ethernet/phytium/phytmac_platform.c +@@ -1,6 +1,10 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Phytium GMAC Platform wrapper. ++ * ++ * Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. ++ * ++ * Author: Wenting Song + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -20,18 +24,16 @@ static const struct phytmac_config phytium_1p0_config = { + | PHYTMAC_CAPS_JUMBO + | PHYTMAC_CAPS_LSO, + .queue_num = 4, +- .tsu_rate = 300000000, + }; + + static const struct phytmac_config phytium_2p0_config = { + .hw_if = &phytmac_2p0_hw, + .caps = PHYTMAC_CAPS_TAILPTR +- | PHYTMAC_CAPS_LPI ++ | PHYTMAC_CAPS_RXPTR + | PHYTMAC_CAPS_LSO + | PHYTMAC_CAPS_MSG + | PHYTMAC_CAPS_JUMBO, + .queue_num = 2, +- .tsu_rate = 300000000, + }; + + #if defined(CONFIG_OF) +@@ -46,7 +48,8 @@ MODULE_DEVICE_TABLE(of, phytmac_dt_ids); + #ifdef CONFIG_ACPI + static const struct acpi_device_id phytmac_acpi_ids[] = { + { .id = "PHYT0046", .driver_data = (kernel_ulong_t)&phytium_1p0_config }, +- { } ++ { .id = "PHYT0056", .driver_data = (kernel_ulong_t)&phytium_2p0_config }, ++ {} + }; + + MODULE_DEVICE_TABLE(acpi, phytmac_acpi_ids); +@@ -54,6 +57,95 @@ MODULE_DEVICE_TABLE(acpi, phytmac_acpi_ids); + #define phytmac_acpi_ids NULL + #endif + ++static const char *phytmac_phy_modes(enum phytmac_interface interface) ++{ ++ switch (interface) { ++ case PHYTMAC_PHY_INTERFACE_MODE_NA: ++ return ""; ++ case PHYTMAC_PHY_INTERFACE_MODE_INTERNAL: ++ return "internal"; ++ case PHYTMAC_PHY_INTERFACE_MODE_MII: ++ return "mii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_GMII: ++ return "gmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_SGMII: ++ return "sgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_TBI: ++ return "tbi"; ++ case PHYTMAC_PHY_INTERFACE_MODE_REVMII: ++ return "rev-mii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RMII: ++ return "rmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RGMII: ++ return "rgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RGMII_ID: ++ return "rgmii-id"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RGMII_RXID: ++ return "rgmii-rxid"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RGMII_TXID: ++ return "rgmii-txid"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RTBI: ++ return "rtbi"; ++ case PHYTMAC_PHY_INTERFACE_MODE_SMII: ++ return "smii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_XGMII: ++ return "xgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_MOCA: ++ return "moca"; ++ case PHYTMAC_PHY_INTERFACE_MODE_QSGMII: ++ return "qsgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_TRGMII: ++ return "trgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_100BASEX: ++ return "100base-x"; ++ case PHYTMAC_PHY_INTERFACE_MODE_1000BASEX: ++ return "1000base-x"; ++ case PHYTMAC_PHY_INTERFACE_MODE_2500BASEX: ++ return "2500base-x"; ++ case PHYTMAC_PHY_INTERFACE_MODE_5GBASER: ++ return "5gbase-r"; ++ case PHYTMAC_PHY_INTERFACE_MODE_RXAUI: ++ return "rxaui"; ++ case PHYTMAC_PHY_INTERFACE_MODE_XAUI: ++ return "xaui"; ++ case PHYTMAC_PHY_INTERFACE_MODE_10GBASER: ++ return "10gbase-r"; ++ case PHYTMAC_PHY_INTERFACE_MODE_USXGMII: ++ return "usxgmii"; ++ case PHYTMAC_PHY_INTERFACE_MODE_10GKR: ++ return "10gbase-kr"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static int phytmac_v2_get_phy_mode(struct platform_device *pdev) ++{ ++ const char *pm; ++ int err, i; ++ int phy_interface; ++ ++ err = device_property_read_string(&pdev->dev, "phy-mode", &pm); ++ if (err < 0) ++ return err; ++ ++ phy_interface = PHYTMAC_PHY_INTERFACE_MODE_MAX + 1; ++ for (i = 0; i < PHYTMAC_PHY_INTERFACE_MODE_MAX; i++) { ++ if (!strcasecmp(pm, phytmac_phy_modes(i))) { ++ phy_interface = i; ++ dev_notice(&pdev->dev, "Phy mode is %s.\n", pm); ++ break; ++ } ++ } ++ ++ if (phy_interface > PHYTMAC_PHY_INTERFACE_MODE_MAX) { ++ dev_err(&pdev->dev, "Invalid phy mode value: %s!\n", pm); ++ return -EINVAL; ++ } ++ ++ return phy_interface; ++} ++ + static int phytmac_get_phy_mode(struct platform_device *pdev) + { + const char *pm; +@@ -79,6 +171,8 @@ static int phytmac_plat_probe(struct platform_device *pdev) + struct phytmac *pdata; + int ret, i; + u32 queue_num; ++ const struct of_device_id *match = NULL; ++ const struct acpi_device_id *match_acpi = NULL; + + pdata = phytmac_alloc_pdata(&pdev->dev); + if (IS_ERR(pdata)) { +@@ -91,8 +185,6 @@ static int phytmac_plat_probe(struct platform_device *pdev) + pdata->platdev = pdev; + + if (pdev->dev.of_node) { +- const struct of_device_id *match; +- + match = of_match_node(phytmac_dt_ids, np); + if (match && match->data) { + phytmac_config = match->data; +@@ -101,11 +193,9 @@ static int phytmac_plat_probe(struct platform_device *pdev) + pdata->queues_max_num = phytmac_config->queue_num; + } + } else if (has_acpi_companion(&pdev->dev)) { +- const struct acpi_device_id *match; +- +- match = acpi_match_device(phytmac_acpi_ids, &pdev->dev); +- if (match && match->driver_data) { +- phytmac_config = (void *)match->driver_data; ++ match_acpi = acpi_match_device(phytmac_acpi_ids, &pdev->dev); ++ if (match_acpi && match_acpi->driver_data) { ++ phytmac_config = (void *)match_acpi->driver_data; + pdata->hw_if = phytmac_config->hw_if; + pdata->capacities = phytmac_config->caps; + pdata->queues_max_num = phytmac_config->queue_num; +@@ -113,7 +203,8 @@ static int phytmac_plat_probe(struct platform_device *pdev) + } + + i = 0; +- pdata->mac_regs = devm_platform_get_and_ioremap_resource(pdev, i, ®s); ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, i); ++ pdata->mac_regs = phytmac_devm_ioremap_resource_np(&pdev->dev, regs); + if (IS_ERR(pdata->mac_regs)) { + dev_err(&pdev->dev, "mac_regs ioremap failed\n"); + ret = PTR_ERR(pdata->mac_regs); +@@ -121,6 +212,18 @@ static int phytmac_plat_probe(struct platform_device *pdev) + } + pdata->ndev->base_addr = regs->start; + ++ if (pdev->dev.of_node && match) { ++ if (!strcmp(match->compatible, "phytium,gmac-1.0")) ++ pdata->version = PHYTMAC_READ(pdata, PHYTMAC_VERSION) & 0xff; ++ else ++ pdata->version = VERSION_V3; ++ } else if (has_acpi_companion(&pdev->dev) && match_acpi) { ++ if (!strcmp(match_acpi->id, "PHYT0046")) ++ pdata->version = PHYTMAC_READ(pdata, PHYTMAC_VERSION) & 0xff; ++ else ++ pdata->version = VERSION_V3; ++ } ++ + if (pdata->capacities & PHYTMAC_CAPS_MSG) { + ++i; + regs = platform_get_resource(pdev, IORESOURCE_MEM, i); +@@ -133,11 +236,10 @@ static int phytmac_plat_probe(struct platform_device *pdev) + } + } + +- if (device_property_read_bool(&pdev->dev, "lpi")) +- pdata->capacities |= PHYTMAC_CAPS_LPI; ++ if (device_property_read_bool(&pdev->dev, "powerctrl")) ++ pdata->capacities |= PHYTMAC_CAPS_PWCTRL; + +- if (pdata->capacities & PHYTMAC_CAPS_LPI) { +- /* lpi resource */ ++ if (pdata->version == VERSION_V3 && pdev->dev.of_node) { + ++i; + regs = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (regs) { +@@ -180,6 +282,14 @@ static int phytmac_plat_probe(struct platform_device *pdev) + else + pdata->phy_interface = ret; + ++ if (pdata->version == VERSION_V3) { ++ ret = phytmac_v2_get_phy_mode(pdev); ++ if (ret < 0) ++ pdata->phytmac_v2_interface = PHYTMAC_PHY_INTERFACE_MODE_USXGMII; ++ else ++ pdata->phytmac_v2_interface = ret; ++ } ++ + ret = phytmac_drv_probe(pdata); + if (ret) + goto err_mem; +@@ -211,6 +321,13 @@ static int phytmac_plat_remove(struct platform_device *pdev) + return 0; + } + ++static void phytmac_plat_shutdown(struct platform_device *pdev) ++{ ++ struct phytmac *pdata = platform_get_drvdata(pdev); ++ ++ phytmac_drv_shutdown(pdata); ++} ++ + static int __maybe_unused phytmac_plat_suspend(struct device *dev) + { + struct phytmac *pdata = dev_get_drvdata(dev); +@@ -239,11 +356,12 @@ static struct platform_driver phytmac_driver = { + .probe = phytmac_plat_probe, + .remove = phytmac_plat_remove, + .driver = { +- .name = PHYTMAC_DRV_NAME, ++ .name = PHYTMAC_PLAT_DRV_NAME, + .of_match_table = of_match_ptr(phytmac_dt_ids), + .acpi_match_table = phytmac_acpi_ids, + .pm = &phytmac_plat_pm_ops, + }, ++ .shutdown = phytmac_plat_shutdown, + }; + + module_platform_driver(phytmac_driver); +diff --git a/drivers/net/ethernet/phytium/phytmac_ptp.c b/drivers/net/ethernet/phytium/phytmac_ptp.c +index 26b1b75edbde..4803842bd7c1 100644 +--- a/drivers/net/ethernet/phytium/phytmac_ptp.c ++++ b/drivers/net/ethernet/phytium/phytmac_ptp.c +@@ -2,6 +2,9 @@ + /** + * 1588 PTP support for Phytium GMAC device. + * ++ * Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. ++ * ++ * Author: Wenting Song + */ + #include + #include +diff --git a/drivers/net/ethernet/phytium/phytmac_ptp.h b/drivers/net/ethernet/phytium/phytmac_ptp.h +index 0ee385e5fe4d..930ca9d864fa 100644 +--- a/drivers/net/ethernet/phytium/phytmac_ptp.h ++++ b/drivers/net/ethernet/phytium/phytmac_ptp.h +@@ -2,6 +2,7 @@ + /* + * Phytium Ethernet Controller driver + * ++ * Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c +index ccd8fefe1a93..b3b11d0fa32a 100644 +--- a/drivers/net/ethernet/phytium/phytmac_v1.c ++++ b/drivers/net/ethernet/phytium/phytmac_v1.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0-only ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ + + #include + #include +@@ -14,6 +15,7 @@ + #include + #include + #include ++#include + #include "phytmac.h" + #include "phytmac_v1.h" + +@@ -149,16 +151,14 @@ static int phytmac_enable_network(struct phytmac *pdata, int enable, int rx_tx) + + static int phytmac_enable_autoneg(struct phytmac *pdata, int enable) + { +- u32 ctrl, old_ctrl; ++ u32 value = PHYTMAC_READ(pdata, PHYTMAC_PCSCTRL); + + if (enable) +- ctrl |= PHYTMAC_BIT(AUTONEG); ++ value |= PHYTMAC_BIT(AUTONEG); + else +- ctrl &= ~PHYTMAC_BIT(AUTONEG); ++ value &= ~PHYTMAC_BIT(AUTONEG); + +- old_ctrl = PHYTMAC_READ(pdata, PHYTMAC_PCSCTRL); +- if (old_ctrl != ctrl) +- PHYTMAC_WRITE(pdata, PHYTMAC_PCSCTRL, ctrl); ++ PHYTMAC_WRITE(pdata, PHYTMAC_PCSCTRL, value); + + return 0; + } +@@ -213,6 +213,11 @@ static int phytmac_mac_linkup(struct phytmac *pdata, phy_interface_t interface, + else + PHYTMAC_WRITE(pdata, PHYTMAC_HCONFIG, PHYTMAC_SPEED_100M); + ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ if (speed == SPEED_2500) ++ phytmac_enable_autoneg(pdata, 0); ++ } ++ + return 0; + } + +@@ -291,7 +296,6 @@ static int phytmac_set_mac_addr(struct phytmac *pdata, const u8 *addr) + + static void phytmac_reset_hw(struct phytmac *pdata) + { +- struct phytmac_queue *queue; + unsigned int q; + u32 ctrl; + +@@ -302,7 +306,7 @@ static void phytmac_reset_hw(struct phytmac *pdata) + PHYTMAC_WRITE(pdata, PHYTMAC_NCTRL, ctrl); + + /* Disable and clear all interrupts and disable queues */ +- for (q = 0, queue = pdata->queues; q < pdata->queues_max_num; ++q, ++queue) { ++ for (q = 0; q < pdata->queues_max_num; ++q) { + if (q == 0) { + PHYTMAC_WRITE(pdata, PHYTMAC_ID, -1); + PHYTMAC_WRITE(pdata, PHYTMAC_IS, -1); +@@ -319,7 +323,10 @@ static void phytmac_reset_hw(struct phytmac *pdata) + PHYTMAC_WRITE(pdata, PHYTMAC_RXPTRH(q), 0); + + if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) +- PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR(q), 0); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_TAILPTR(q), 0); ++ ++ if (pdata->capacities & PHYTMAC_CAPS_RXPTR) ++ PHYTMAC_WRITE(pdata, PHYTMAC_RX_TAILPTR(q), 0); + } + } + +@@ -354,6 +361,7 @@ static int phytmac_init_hw(struct phytmac *pdata) + u32 config = PHYTMAC_READ(pdata, PHYTMAC_NCONFIG); + u32 dmaconfig; + u32 nctrlconfig; ++ u32 ptrconfig = 0; + + nctrlconfig = PHYTMAC_READ(pdata, PHYTMAC_NCTRL); + nctrlconfig |= PHYTMAC_BIT(MPE); +@@ -415,7 +423,14 @@ static int phytmac_init_hw(struct phytmac *pdata) + PHYTMAC_WRITE(pdata, PHYTMAC_DCONFIG, dmaconfig); + + if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) +- PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_ENABLE, PHYTMAC_BIT(TXTAIL_ENABLE)); ++ ptrconfig |= PHYTMAC_BIT(TXPTR_EN); ++ if (pdata->capacities & PHYTMAC_CAPS_RXPTR) ++ ptrconfig |= PHYTMAC_BIT(RXPTR_EN); ++ ++ PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_ENABLE, ptrconfig); ++ ++ if (pdata->capacities & PHYTMAC_CAPS_START) ++ PHYTMAC_WRITE(pdata, PHYTMAC_TXSTARTSEL, PHYTMAC_BIT(TSTARTSEL_ENABLE)); + + if (phy_interface_mode_is_8023z(pdata->phy_interface)) + phytmac_pcs_software_reset(pdata, 1); +@@ -427,8 +442,48 @@ static int phytmac_powerup_hw(struct phytmac *pdata, int on) + { + u32 status, data0, data1, rdata1; + int ret; ++ acpi_handle handle; ++ union acpi_object args[3]; ++ struct acpi_object_list arg_list = { ++ .pointer = args, ++ .count = ARRAY_SIZE(args), ++ }; ++ acpi_status acpi_sts; ++ unsigned long long rv; ++ ++ if (!(pdata->capacities & PHYTMAC_CAPS_PWCTRL)) { ++ pdata->power_state = on; ++ return 0; ++ } ++ ++ if (has_acpi_companion(pdata->dev)) { ++#ifdef CONFIG_ACPI ++ handle = ACPI_HANDLE(pdata->dev); ++ ++ netdev_info(pdata->ndev, "set gmac power %s\n", ++ on == PHYTMAC_POWERON ? "on" : "off"); ++ args[0].type = ACPI_TYPE_INTEGER; ++ args[0].integer.value = PHYTMAC_PWCTL_GMAC_ID; ++ args[1].type = ACPI_TYPE_INTEGER; ++ args[1].integer.value = PHYTMAC_PWCTL_DEFAULT_VAL; ++ args[2].type = ACPI_TYPE_INTEGER; ++ args[2].integer.value = PHYTMAC_PWCTL_DEFAULT_VAL; + +- if (pdata->capacities & PHYTMAC_CAPS_LPI) { ++ if (on == PHYTMAC_POWERON) { ++ acpi_sts = acpi_evaluate_integer(handle, "PPWO", &arg_list, &rv); ++ if (ACPI_FAILURE(acpi_sts)) ++ netdev_err(pdata->ndev, "NO PPWO Method\n"); ++ if (rv) ++ netdev_err(pdata->ndev, "Failed to power on\n"); ++ } else { ++ acpi_sts = acpi_evaluate_integer(handle, "PPWD", &arg_list, &rv); ++ if (ACPI_FAILURE(acpi_sts)) ++ netdev_err(pdata->ndev, "NO PPWD Method\n"); ++ if (rv) ++ netdev_err(pdata->ndev, "Failed to power off\n"); ++ } ++#endif /* CONFIG_ACPI */ ++ } else { + ret = readx_poll_timeout(PHYTMAC_READ_STAT, pdata, status, !status, + 1, PHYTMAC_TIMEOUT); + if (ret) +@@ -461,16 +516,17 @@ static int phytmac_powerup_hw(struct phytmac *pdata, int on) + data0 & PHYTMAC_BIT(DATA0_FREE), + 1, PHYTMAC_TIMEOUT); + if (ret) +- netdev_err(pdata->ndev, "mnh data0 is busy"); ++ netdev_err(pdata->ndev, "mnh data0 is busy\n"); + + rdata1 = PHYTMAC_MHU_READ(pdata, PHYTMAC_MHU_CPP_DATA1); + if (rdata1 == data1) + netdev_err(pdata->ndev, "gmac power %s success, data1 = %x, rdata1=%x\n", +- on ? "up" : "down", data1, rdata1); ++ on == PHYTMAC_POWERON ? "up" : "down", data1, rdata1); + else + netdev_err(pdata->ndev, "gmac power %s failed, data1 = %x, rdata1=%x\n", +- on ? "up" : "down", data1, rdata1); ++ on == PHYTMAC_POWERON ? "up" : "down", data1, rdata1); + } ++ + pdata->power_state = on; + + return 0; +@@ -503,16 +559,18 @@ static int phytmac_set_wake(struct phytmac *pdata, int wake) + return 0; + } + +-static void phytmac_mdio_idle(struct phytmac *pdata) ++static int phytmac_mdio_idle(struct phytmac *pdata) + { + u32 val; ++ int ret; + + /* wait for end of transfer */ +- val = PHYTMAC_READ(pdata, PHYTMAC_NSTATUS); +- while (!(val & PHYTMAC_BIT(MDIO_IDLE))) { +- cpu_relax(); +- val = PHYTMAC_READ(pdata, PHYTMAC_NSTATUS); +- } ++ ret = readx_poll_timeout(PHYTMAC_READ_NSTATUS, pdata, val, val & PHYTMAC_BIT(MDIO_IDLE), ++ 1, PHYTMAC_MDIO_TIMEOUT); ++ if (ret) ++ netdev_err(pdata->ndev, "mdio wait for idle time out!"); ++ ++ return ret; + } + + static int phytmac_mdio_data_read(struct phytmac *pdata, int mii_id, int regnum, int is_c45) +@@ -613,6 +671,9 @@ static int phytmac_get_feature_all(struct phytmac *pdata) + /* max rx fs */ + pdata->max_rx_fs = PHYTMAC_READ_BITS(pdata, PHYTMAC_DEFAULT3, SCR2CMP); + ++ if (pdata->version == VERSION_V3) ++ pdata->capacities |= PHYTMAC_CAPS_RXPTR; ++ + if (netif_msg_hw(pdata)) + netdev_info(pdata->ndev, "get feature queue_num=%d, daw=%d, dbw=%d, rx_fs=%d, rx_bd=%d, tx_bd=%d\n", + pdata->queues_num, pdata->dma_addr_width, pdata->dma_data_width, +@@ -743,7 +804,7 @@ static int phytmac_init_ring_hw(struct phytmac *pdata) + PHYTMAC_WRITE(pdata, PHYTMAC_RXPTRH(q), upper_32_bits(queue->rx_ring_addr)); + + if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) +- PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR(q), queue->tx_tail); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_TAILPTR(q), queue->tx_tail); + } + + return 0; +@@ -930,7 +991,16 @@ static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, + static unsigned int phytmac_zero_rx_desc_addr(struct phytmac_dma_desc *desc) + { + desc->desc2 = 0; +- desc->desc0 = PHYTMAC_BIT(RX_USED); ++ desc->desc0 = (desc->desc0 & PHYTMAC_BIT(RX_TS_VALID)) | PHYTMAC_BIT(RX_USED); ++ ++ return 0; ++} ++ ++static unsigned int phytmac_zero_tx_desc(struct phytmac_dma_desc *desc) ++{ ++ desc->desc2 = 0; ++ desc->desc0 = 0; ++ desc->desc1 &= ~PHYTMAC_BIT(TX_USED); + + return 0; + } +@@ -940,27 +1010,19 @@ static void phytmac_tx_start(struct phytmac_queue *queue) + struct phytmac *pdata = queue->pdata; + + if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) +- PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR(queue->index), ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_TAILPTR(queue->index), + PHYTMAC_BIT(TXTAIL_UPDATE) | queue->tx_tail); + +- if (pdata->capacities & PHYTMAC_CAPS_START) +- PHYTMAC_WRITE(pdata, PHYTMAC_NCTRL, +- PHYTMAC_READ(pdata, PHYTMAC_NCTRL) | PHYTMAC_BIT(TSTART)); ++ if (likely(pdata->capacities & PHYTMAC_CAPS_START)) ++ PHYTMAC_WRITE(pdata, PHYTMAC_TXSTART, PHYTMAC_BIT(TSTART)); + } + +-static void phytmac_restart(struct phytmac *pdata) ++static void phytmac_update_rx_tail(struct phytmac_queue *queue) + { +- int q; +- struct phytmac_queue *queue; ++ struct phytmac *pdata = queue->pdata; + +- for (q = 0; q < pdata->queues_num; q++) { +- queue = &pdata->queues[q]; +- if (queue->tx_head != queue->tx_tail) { +- PHYTMAC_WRITE(pdata, PHYTMAC_NCTRL, +- PHYTMAC_READ(pdata, PHYTMAC_NCTRL) | PHYTMAC_BIT(TSTART)); +- break; +- } +- } ++ if (pdata->capacities & PHYTMAC_CAPS_RXPTR) ++ PHYTMAC_WRITE(pdata, PHYTMAC_RX_TAILPTR(queue->index), queue->rx_head); + } + + static int phytmac_tx_complete(const struct phytmac_dma_desc *desc) +@@ -1145,20 +1207,20 @@ static void phytmac_clear_tx_desc(struct phytmac_queue *queue) + desc->desc1 |= PHYTMAC_BIT(TX_WRAP); + + if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) +- PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR(queue->index), queue->tx_tail); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_TAILPTR(queue->index), queue->tx_tail); + } + + static void phytmac_get_hw_stats(struct phytmac *pdata) + { +- u32 stats[45]; ++ u32 stats[PHYTMAC_STATIS_REG_NUM]; + int i, j; + u64 val; + u64 *p = &pdata->stats.tx_octets; + +- for (i = 0 ; i < 45; i++) ++ for (i = 0 ; i < PHYTMAC_STATIS_REG_NUM; i++) + stats[i] = PHYTMAC_READ(pdata, PHYTMAC_OCTTX + i * 4); + +- for (i = 0, j = 0; i < 45; i++) { ++ for (i = 0, j = 0; i < PHYTMAC_STATIS_REG_NUM; i++) { + if (i == 0 || i == 20) { + val = (u64)stats[i + 1] << 32 | stats[i]; + *p += val; +@@ -1342,6 +1404,7 @@ struct phytmac_hw_if phytmac_1p0_hw = { + .get_stats = phytmac_get_hw_stats, + .set_mac_address = phytmac_set_mac_addr, + .get_mac_address = phytmac_get_mac_addr, ++ .mdio_idle = phytmac_mdio_idle, + .mdio_read = phytmac_mdio_data_read, + .mdio_write = phytmac_mdio_data_write, + .poweron = phytmac_powerup_hw, +@@ -1373,7 +1436,7 @@ struct phytmac_hw_if phytmac_1p0_hw = { + /* tx and rx */ + .tx_map = phytmac_tx_map_desc, + .transmit = phytmac_tx_start, +- .restart = phytmac_restart, ++ .update_rx_tail = phytmac_update_rx_tail, + .tx_complete = phytmac_tx_complete, + .rx_complete = phytmac_rx_complete, + .get_rx_pkt_len = phytmac_rx_pkt_len, +@@ -1386,6 +1449,7 @@ struct phytmac_hw_if phytmac_1p0_hw = { + .clear_rx_desc = phytmac_clear_rx_desc, + .clear_tx_desc = phytmac_clear_tx_desc, + .zero_rx_desc_addr = phytmac_zero_rx_desc_addr, ++ .zero_tx_desc = phytmac_zero_tx_desc, + /* ptp */ + .init_ts_hw = phytmac_ptp_init_hw, + .set_time = phytmac_set_time, +diff --git a/drivers/net/ethernet/phytium/phytmac_v1.h b/drivers/net/ethernet/phytium/phytmac_v1.h +index 6936cb0906bf..7a56fdfcd3e2 100644 +--- a/drivers/net/ethernet/phytium/phytmac_v1.h ++++ b/drivers/net/ethernet/phytium/phytmac_v1.h +@@ -1,4 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ ++ + #ifndef _PHYTMAC_V1_H + #define _PHYTMAC_V1_H + +@@ -53,6 +55,9 @@ extern struct phytmac_hw_if phytmac_1p0_hw; + #define PHYTMAC_USXSTATUS 0x0A88 + #define PHYTMAC_TXBDCTRL 0x04CC + #define PHYTMAC_RXBDCTRL 0x04D0 ++#define PHYTMAC_TXSTART 0x0E70 ++#define PHYTMAC_TXSTARTSEL 0x0E74 ++#define PHYTMAC_VERSION 0x0FF0 + + /* Fdir match registers */ + #define PHYTMAC_FDIR(i) (0x0540 + ((i) << 2)) +@@ -75,7 +80,8 @@ extern struct phytmac_hw_if phytmac_1p0_hw; + #define PHYTMAC_IDR(i) (0x0620 + ((i) << 2)) + #define PHYTMAC_IMR(i) (0x0640 + ((i) << 2)) + #define PHYTMAC_TAIL_ENABLE (0x0e7c) +-#define PHYTMAC_TAILPTR(i) (0x0e80 + ((i) << 2)) ++#define PHYTMAC_TX_TAILPTR(i) (0x0e80 + ((i) << 2)) ++#define PHYTMAC_RX_TAILPTR(i) (0x0ec0 + ((i) << 2)) + + #define PHYTMAC_PHY_INT_ENABLE 0x1C88 + #define PHYTMAC_PHY_INT_CLEAR 0x1C8C +@@ -363,8 +369,11 @@ extern struct phytmac_hw_if phytmac_1p0_hw; + #define PHYTMAC_TXTAIL_UPDATE_WIDTH 1 + + /* Bitfields in TAIL_ENABLE */ +-#define PHYTMAC_TXTAIL_ENABLE_INDEX 0 /* Enable tx tail */ +-#define PHYTMAC_TXTAIL_ENABLE_WIDTH 1 ++#define PHYTMAC_TXPTR_EN_INDEX 0 /* Enable tx tail */ ++#define PHYTMAC_TXPTR_EN_WIDTH 1 ++ ++#define PHYTMAC_RXPTR_EN_INDEX 16 /* Enable rx tail */ ++#define PHYTMAC_RXPTR_EN_WIDTH 1 + + /* Bitfields in INT ENABLE */ + #define PHYTMAC_WOL_RECEIVE_ENABLE_INDEX 28 /* Enable wol_event_receieve */ +@@ -374,6 +383,10 @@ extern struct phytmac_hw_if phytmac_1p0_hw; + #define PHYTMAC_WOL_RECEIVE_DISABLE_INDEX 28 /* Disable wol_event_receieve */ + #define PHYTMAC_WOL_RECEIVE_DISABLE_WIDTH 1 + ++/* Bitfields in PHYTMAC_TXSTARTSEL */ ++#define PHYTMAC_TSTARTSEL_ENABLE_INDEX 0 /* Enable Tstart_sel */ ++#define PHYTMAC_TSTARTSEL_ENABLE_WIDTH 1 ++ + #define PHYTMAC_TSEC_WIDTH (PHYTMAC_SECH_WIDTH + PHYTMAC_SECL_WIDTH) + #define SEC_MAX_VAL (((u64)1 << PHYTMAC_TSEC_WIDTH) - 1) + #define NSEC_MAX_VAL ((1 << PHYTMAC_NSEC_WIDTH) - 1) +diff --git a/drivers/net/ethernet/phytium/phytmac_v2.c b/drivers/net/ethernet/phytium/phytmac_v2.c +index a996e38d8640..c72eefa2680c 100644 +--- a/drivers/net/ethernet/phytium/phytmac_v2.c ++++ b/drivers/net/ethernet/phytium/phytmac_v2.c +@@ -1,4 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ ++ + #include + #include + #include +@@ -13,54 +15,91 @@ + #include + #include + #include ++#include + #include "phytmac.h" + #include "phytmac_v2.h" + +-static int phytmac_msg_send(struct phytmac *pdata, u16 cmd_id, +- u16 cmd_subid, void *data, int len, int wait) ++static int phytmac_v2_msg_send(struct phytmac *pdata, u16 cmd_id, ++ u16 cmd_subid, void *data, int len, int wait) + { +- int index = 0; ++ u32 tx_head, tx_tail, ring_size; + struct phytmac_msg_info msg; + struct phytmac_msg_info msg_rx; ++ u32 retry = 0; + int ret = 0; + +- ++pdata->msg_ring.tx_msg_tail; +- if (pdata->msg_ring.tx_msg_tail > pdata->msg_ring.tx_msg_ring_size) +- pdata->msg_ring.tx_msg_tail = 1; +- index = pdata->msg_ring.tx_msg_tail; ++ spin_lock(&pdata->msg_ring.msg_lock); ++ tx_head = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_HEAD) & 0xff; ++ tx_tail = phytmac_v2_tx_ring_wrap(pdata, pdata->msg_ring.tx_msg_wr_tail); ++ pdata->msg_ring.tx_msg_rd_tail = tx_tail; ++ ring_size = pdata->msg_ring.tx_msg_ring_size; ++ ++ while ((tx_tail + 1) % ring_size == tx_head) { ++ udelay(1); ++ tx_head = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_HEAD) & 0xff; ++ retry++; ++ if (retry >= PHYTMAC_RETRY_TIMES) { ++ netdev_err(pdata->ndev, ++ "Time out waiting for Tx msg ring free, tx_tail:0x%x, tx_head:0x%x", ++ tx_tail, tx_head); ++ spin_unlock(&pdata->msg_ring.msg_lock); ++ return -EINVAL; ++ } ++ } + ++ retry = 0; + wait = 1; + memset(&msg, 0, sizeof(msg)); + memset(&msg_rx, 0, sizeof(msg_rx)); +- msg.module_id = PHYTMAC_MODULE_ID_GMAC; +- msg.cmd_id = cmd_id; ++ msg.cmd_type = cmd_id; + msg.cmd_subid = cmd_subid; +- msg.flags = PHYTMAC_FLAGS_MSG_NOINT; +- +- if (len) ++ if (len > 0 && len <= PHYTMAC_MSG_PARA_LEN) { + memcpy(&msg.para[0], data, len); ++ } else if (len > PHYTMAC_MSG_PARA_LEN) { ++ netdev_err(pdata->ndev, "Tx msg para len %d is greater than the max len %d", ++ len, PHYTMAC_MSG_PARA_LEN); ++ spin_unlock(&pdata->msg_ring.msg_lock); ++ return -EINVAL; ++ } + + if (netif_msg_hw(pdata)) { +- netdev_info(pdata->ndev, "tx msg: cmdid=%d, subid=%d, flags=%d, len=%d, tail=%d\n", +- msg.cmd_id, msg.cmd_subid, msg.flags, len, pdata->msg_ring.tx_msg_tail); ++ netdev_info(pdata->ndev, "Tx msg: cmdid:%d, subid:%d, status0:%d, len:%d, tail:%d", ++ msg.cmd_type, msg.cmd_subid, msg.status0, len, tx_tail); + } + +- memcpy(pdata->msg_regs + PHYTMAC_MSG(index), &msg, sizeof(msg)); +- PHYTMAC_WRITE(pdata, PHYTMAC_TX_MSG_TAIL, +- pdata->msg_ring.tx_msg_tail | PHYTMAC_BIT(TX_MSG_INT)); ++ memcpy(pdata->msg_regs + PHYTMAC_MSG(tx_tail), &msg, sizeof(msg)); ++ tx_tail = phytmac_v2_tx_ring_wrap(pdata, ++tx_tail); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_MSG_TAIL, tx_tail | PHYTMAC_BIT(TX_MSG_INT)); ++ pdata->msg_ring.tx_msg_wr_tail = tx_tail; + + if (wait) { +- memcpy(&msg_rx, pdata->msg_regs + PHYTMAC_MSG(index), MSG_HDR_LEN); +- while (!(msg_rx.flags & 0x1)) { +- cpu_relax(); +- memcpy(&msg_rx, pdata->msg_regs + PHYTMAC_MSG(index), MSG_HDR_LEN); ++ tx_head = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_HEAD) & 0xff; ++ while (tx_head != tx_tail) { ++ udelay(1); ++ tx_head = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_HEAD) & 0xff; ++ retry++; ++ if (retry >= PHYTMAC_RETRY_TIMES) { ++ netdev_err(pdata->ndev, "Msg process time out!"); ++ spin_unlock(&pdata->msg_ring.msg_lock); ++ return -EINVAL; ++ } ++ } ++ ++ memcpy(&msg_rx, pdata->msg_regs + PHYTMAC_MSG(pdata->msg_ring.tx_msg_rd_tail), ++ PHYTMAC_MSG_HDR_LEN); ++ if (!(msg_rx.status0 & PHYTMAC_CMD_PRC_SUCCESS)) { ++ netdev_err(pdata->ndev, "Msg process error, cmdid:%d, subid:%d, status0:%d, tail:%d", ++ msg.cmd_type, msg.cmd_subid, msg.status0, tx_tail); ++ spin_unlock(&pdata->msg_ring.msg_lock); ++ return -EINVAL; + } + } + ++ spin_unlock(&pdata->msg_ring.msg_lock); + return ret; + } + +-void phytmac_reset_hw(struct phytmac *pdata) ++static void phytmac_v2_reset_hw(struct phytmac *pdata) + { + int q; + u16 cmd_id, cmd_subid; +@@ -70,26 +109,27 @@ void phytmac_reset_hw(struct phytmac *pdata) + for (q = 0; q < pdata->queues_max_num; ++q) { + PHYTMAC_WRITE(pdata, PHYTMAC_INT_DR(q), -1); + PHYTMAC_WRITE(pdata, PHYTMAC_INT_SR(q), -1); +- PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_PTR(q), 0); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_PTR(q), 0); ++ PHYTMAC_WRITE(pdata, PHYTMAC_RX_PTR(q), 0); + } + + /* reset hw rx/tx enable */ + cmd_id = PHYTMAC_MSG_CMD_DEFAULT; + cmd_subid = PHYTMAC_MSG_CMD_DEFAULT_RESET_HW; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + + /* reset tx ring */ + memset(&ring, 0, sizeof(ring)); + ring.queue_num = pdata->queues_max_num; + cmd_subid = PHYTMAC_MSG_CMD_DEFAULT_RESET_TX_QUEUE; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&ring), sizeof(ring), 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&ring), sizeof(ring), 0); + + /* reset rx ring */ + cmd_subid = PHYTMAC_MSG_CMD_DEFAULT_RESET_RX_QUEUE; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&ring), sizeof(ring), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&ring), sizeof(ring), 1); + } + +-static int phytmac_get_mac_addr(struct phytmac *pdata, u8 *addr) ++static int phytmac_v2_get_mac_addr(struct phytmac *pdata, u8 *addr) + { + int index; + u16 cmd_id, cmd_subid; +@@ -97,12 +137,11 @@ static int phytmac_get_mac_addr(struct phytmac *pdata, u8 *addr) + + cmd_id = PHYTMAC_MSG_CMD_GET; + cmd_subid = PHYTMAC_MSG_CMD_GET_ADDR; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + +- index = pdata->msg_ring.tx_msg_tail; +- if (index <= 0) +- index += pdata->msg_ring.tx_msg_ring_size; +- memcpy(¶, pdata->msg_regs + PHYTMAC_MSG(index) + MSG_HDR_LEN, 8); ++ index = phytmac_v2_tx_ring_wrap(pdata, pdata->msg_ring.tx_msg_rd_tail); ++ memcpy(¶, pdata->msg_regs + PHYTMAC_MSG(index) + PHYTMAC_MSG_HDR_LEN, ++ sizeof(struct phytmac_mac)); + + addr[0] = para.addrl & 0xff; + addr[1] = (para.addrl >> 8) & 0xff; +@@ -114,7 +153,7 @@ static int phytmac_get_mac_addr(struct phytmac *pdata, u8 *addr) + return 0; + } + +-int phytmac_set_mac_addr(struct phytmac *pdata, const u8 *addr) ++static int phytmac_v2_set_mac_addr(struct phytmac *pdata, const u8 *addr) + { + u16 cmd_id; + u16 cmd_subid; +@@ -126,46 +165,78 @@ int phytmac_set_mac_addr(struct phytmac *pdata, const u8 *addr) + para.addrl = cpu_to_le32(*((u32 *)addr)); + para.addrh = cpu_to_le16(*((u16 *)(addr + 4))); + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ ++ return 0; ++} ++ ++static int phytmac_v2_pcs_software_reset(struct phytmac *pdata, int reset) ++{ ++ u16 cmd_id; ++ u16 cmd_subid; ++ ++ cmd_id = PHYTMAC_MSG_CMD_SET; ++ if (reset) ++ cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_PCS_RESET; ++ else ++ cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_PCS_RESET; ++ ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_init_hw(struct phytmac *pdata) ++static int phytmac_v2_init_hw(struct phytmac *pdata) + { + u16 cmd_id, cmd_subid; + struct phytmac_dma_info dma; + struct phytmac_eth_info eth; ++ u32 ptrconfig = 0; ++ u8 mdc; + +- phytmac_set_mac_addr(pdata, pdata->ndev->dev_addr); ++ if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) ++ ptrconfig |= PHYTMAC_BIT(TXTAIL_EN); ++ if (pdata->capacities & PHYTMAC_CAPS_RXPTR) ++ ptrconfig |= PHYTMAC_BIT(RXTAIL_EN); ++ ++ PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR_ENABLE, ptrconfig); ++ ++ if (pdata->mii_bus) { ++ cmd_id = PHYTMAC_MSG_CMD_SET; ++ cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_MDIO; ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ } ++ ++ phytmac_v2_set_mac_addr(pdata, pdata->ndev->dev_addr); + + cmd_id = PHYTMAC_MSG_CMD_SET; + if (pdata->capacities & PHYTMAC_CAPS_JUMBO) + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_JUMBO; + else + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_1536_FRAMES; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + + if (pdata->ndev->flags & IFF_PROMISC) { + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_PROMISE; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + } + + if (pdata->ndev->features & NETIF_F_RXCSUM) { + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_RXCSUM; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + } + +- if (!(pdata->ndev->flags & IFF_BROADCAST)) { ++ if (pdata->ndev->flags & IFF_BROADCAST) ++ cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_BC; ++ else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_BC; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); +- } ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_PAUSE; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_STRIPCRC; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 0); + + memset(&dma, 0, sizeof(dma)); + cmd_subid = PHYTMAC_MSG_CMD_SET_DMA; +@@ -176,22 +247,31 @@ static int phytmac_init_hw(struct phytmac *pdata) + dma.hw_dma_cap |= HW_DMA_CAP_CSUM; + if (IS_REACHABLE(CONFIG_PHYTMAC_ENABLE_PTP)) + dma.hw_dma_cap |= HW_DMA_CAP_PTP; ++ if (pdata->dma_data_width == PHYTMAC_DBW32) ++ dma.hw_dma_cap |= HW_DMA_CAP_DDW32; + if (pdata->dma_data_width == PHYTMAC_DBW64) + dma.hw_dma_cap |= HW_DMA_CAP_DDW64; + if (pdata->dma_data_width == PHYTMAC_DBW128) + dma.hw_dma_cap |= HW_DMA_CAP_DDW128; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)&dma, sizeof(dma), 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)&dma, sizeof(dma), 0); ++ ++ cmd_subid = PHYTMAC_MSG_CMD_SET_MDC; ++ mdc = PHYTMAC_CLK_DIV96; ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&mdc), sizeof(mdc), 0); + + memset(ð, 0, sizeof(eth)); + cmd_subid = PHYTMAC_MSG_CMD_SET_ETH_MATCH; + eth.index = 0; + eth.etype = (uint16_t)ETH_P_IP; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)ð, sizeof(eth), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)ð, sizeof(eth), 1); ++ ++ if (phy_interface_mode_is_8023z(pdata->phy_interface)) ++ phytmac_v2_pcs_software_reset(pdata, 1); + + return 0; + } + +-static int phytmac_enable_multicast(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_multicast(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -201,11 +281,11 @@ static int phytmac_enable_multicast(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_MC; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + return 0; + } + +-static int phytmac_set_mc_hash(struct phytmac *pdata, unsigned long *mc_filter) ++static int phytmac_v2_set_mc_hash(struct phytmac *pdata, unsigned long *mc_filter) + { + u16 cmd_id, cmd_subid; + struct phytmac_mc_info para; +@@ -215,12 +295,12 @@ static int phytmac_set_mc_hash(struct phytmac *pdata, unsigned long *mc_filter) + cmd_subid = PHYTMAC_MSG_CMD_SET_ENABLE_HASH_MC; + para.mc_bottom = (u32)mc_filter[0]; + para.mc_top = (u32)mc_filter[1]; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); + + return 0; + } + +-static int phytmac_init_ring_hw(struct phytmac *pdata) ++static int phytmac_v2_init_ring_hw(struct phytmac *pdata) + { + u16 cmd_id, cmd_subid; + struct phytmac_ring_info rxring; +@@ -239,45 +319,43 @@ static int phytmac_init_ring_hw(struct phytmac *pdata) + txring.hw_dma_cap |= HW_DMA_CAP_64B; + rxring.hw_dma_cap |= HW_DMA_CAP_64B; + for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) { +- PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_PTR(q), queue->tx_head); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_PTR(q), queue->tx_head); + txring.addr[q] = queue->tx_ring_addr; + rxring.addr[q] = queue->rx_ring_addr; + } + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&txring), sizeof(txring), 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&txring), sizeof(txring), 0); + + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_DMA_RX_BUFSIZE; + rxbuf.queue_num = pdata->queues_num; + rxbuf.buffer_size = pdata->rx_buffer_len / 64; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxbuf), sizeof(rxbuf), 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxbuf), sizeof(rxbuf), 0); + + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_INIT_RX_RING; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxring), sizeof(rxring), 0); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxring), sizeof(rxring), 1); + + return 0; + } + +-int phytmac_init_msg_ring(struct phytmac *pdata) ++static int phytmac_v2_init_msg_ring(struct phytmac *pdata) + { +- u32 size = 0; +- +- pdata->msg_ring.tx_msg_tail = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_TAIL) & 0xff; +- size = PHYTMAC_READ_BITS(pdata, PHYTMAC_SIZE, TXRING_SIZE); +- pdata->msg_ring.tx_msg_ring_size = size; +- if (pdata->msg_ring.tx_msg_tail == size) +- pdata->msg_ring.tx_msg_tail = 0; ++ u32 tx_msg_tail; + ++ pdata->msg_ring.tx_msg_ring_size = PHYTMAC_READ_BITS(pdata, PHYTMAC_SIZE, TXRING_SIZE); ++ tx_msg_tail = PHYTMAC_READ(pdata, PHYTMAC_TX_MSG_TAIL) & 0xff; ++ pdata->msg_ring.tx_msg_wr_tail = phytmac_v2_tx_ring_wrap(pdata, tx_msg_tail); ++ pdata->msg_ring.tx_msg_rd_tail = pdata->msg_ring.tx_msg_wr_tail; + PHYTMAC_WRITE(pdata, PHYTMAC_MSG_IMR, 0xfffffffe); + if (netif_msg_hw(pdata)) +- netdev_info(pdata->ndev, "mac msg ring: tx_msg_ring_size=%d, tx_msg_tail=%d\n", +- size, pdata->msg_ring.tx_msg_tail); ++ netdev_info(pdata->ndev, "Msg ring size:%d, tx msg tail=%d\n", ++ pdata->msg_ring.tx_msg_ring_size, tx_msg_tail); + + return 0; + } + +-static int phytmac_get_feature_all(struct phytmac *pdata) ++static int phytmac_v2_get_feature_all(struct phytmac *pdata) + { + u16 cmd_id, cmd_subid; + int index; +@@ -286,13 +364,9 @@ static int phytmac_get_feature_all(struct phytmac *pdata) + memset(¶, 0, sizeof(para)); + cmd_id = PHYTMAC_MSG_CMD_GET; + cmd_subid = PHYTMAC_MSG_CMD_GET_CAPS; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); +- +- index = pdata->msg_ring.tx_msg_tail; +- if (index <= 0) +- index += pdata->msg_ring.tx_msg_ring_size; +- +- memcpy(¶, pdata->msg_regs + PHYTMAC_MSG(index) + MSG_HDR_LEN, ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ index = phytmac_v2_tx_ring_wrap(pdata, pdata->msg_ring.tx_msg_rd_tail); ++ memcpy(¶, pdata->msg_regs + PHYTMAC_MSG(index) + PHYTMAC_MSG_HDR_LEN, + sizeof(struct phytmac_feature)); + + pdata->queues_max_num = para.queue_num; +@@ -302,10 +376,13 @@ static int phytmac_get_feature_all(struct phytmac *pdata) + pdata->dma_addr_width = 32; + pdata->dma_data_width = para.dma_data_width; + pdata->max_rx_fs = para.max_rx_fs; +- pdata->tx_bd_prefetch = (2 << (para.tx_bd_prefetch - 1)) * +- sizeof(struct phytmac_dma_desc); +- pdata->rx_bd_prefetch = (2 << (para.rx_bd_prefetch - 1)) * +- sizeof(struct phytmac_dma_desc); ++ ++ if (para.tx_bd_prefetch) ++ pdata->tx_bd_prefetch = (2 << (para.tx_bd_prefetch - 1)) * ++ sizeof(struct phytmac_dma_desc); ++ if (para.rx_bd_prefetch) ++ pdata->rx_bd_prefetch = (2 << (para.rx_bd_prefetch - 1)) * ++ sizeof(struct phytmac_dma_desc); + + if (netif_msg_hw(pdata)) { + netdev_info(pdata->ndev, "feature qnum=%d, daw=%d, dbw=%d, rxfs=%d, rxbd=%d, txbd=%d\n", +@@ -316,56 +393,42 @@ static int phytmac_get_feature_all(struct phytmac *pdata) + return 0; + } + +-void phytmac_get_regs(struct phytmac *pdata, u32 *reg_buff) ++static void phytmac_v2_get_regs(struct phytmac *pdata, u32 *reg_buff) + { + u16 cmd_id, cmd_subid; +- u16 reg_num; + int index; ++ struct phytmac_ethtool_reg msg; + ++ memset(&msg, 0, sizeof(msg)); + cmd_id = PHYTMAC_MSG_CMD_GET; +- cmd_subid = PHYTMAC_MSG_CMD_GET_REG_READ; +- reg_num = 16; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)®_num, 2, 1); +- +- index = pdata->msg_ring.tx_msg_tail; +- if (index <= 0) +- index += pdata->msg_ring.tx_msg_ring_size; +- +- memcpy(®_buff, pdata->msg_regs + PHYTMAC_MSG(index) + MSG_HDR_LEN, 64); ++ cmd_subid = PHYTMAC_MSG_CMD_GET_REGS_FOR_ETHTOOL; ++ msg.interface = pdata->phytmac_v2_interface; ++ /* There are 16 regs in total, read 14 regs at first time, read 2 regs at last time */ ++ msg.cnt = 0; ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&msg), sizeof(msg), 1); ++ index = phytmac_v2_tx_ring_wrap(pdata, pdata->msg_ring.tx_msg_rd_tail); ++ memcpy(reg_buff, pdata->msg_regs + PHYTMAC_MSG(index) + PHYTMAC_MSG_HDR_LEN, ++ PHYTMAC_MSG_PARA_LEN); ++ ++ msg.cnt = 1; ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&msg), sizeof(msg), 1); ++ index = phytmac_v2_tx_ring_wrap(pdata, pdata->msg_ring.tx_msg_rd_tail); ++ memcpy(reg_buff + PHYTMAC_MSG_PARA_LEN / sizeof(u32), pdata->msg_regs + ++ PHYTMAC_MSG(index) + PHYTMAC_MSG_HDR_LEN, ++ PHYTMAC_ETHTOOLD_REGS_LEN - PHYTMAC_MSG_PARA_LEN); + } + +-static void phytmac_get_hw_stats(struct phytmac *pdata) ++static void phytmac_v2_get_hw_stats(struct phytmac *pdata) + { +- u16 cmd_id, cmd_subid; +- u8 count; +- int i, j, index; +- u32 stats[48]; ++ u32 stats[PHYTMAC_STATIS_REG_NUM]; ++ int i, j; + u64 val; + u64 *p = &pdata->stats.tx_octets; + +- cmd_id = PHYTMAC_MSG_CMD_GET; +- cmd_subid = PHYTMAC_MSG_CMD_GET_STATS; +- count = 1; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)&count, sizeof(count), 0); +- +- cmd_id = PHYTMAC_MSG_CMD_GET; +- cmd_subid = PHYTMAC_MSG_CMD_GET_STATS; +- count = 2; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)&count, sizeof(count), 0); +- +- cmd_id = PHYTMAC_MSG_CMD_GET; +- cmd_subid = PHYTMAC_MSG_CMD_GET_STATS; +- count = 3; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)&count, sizeof(count), 1); +- +- for (i = 0; i < 3; i++) { +- index = pdata->msg_ring.tx_msg_tail + i - 2; +- if (index <= 0) +- index += pdata->msg_ring.tx_msg_ring_size; +- memcpy(&stats[i * 16], pdata->msg_regs + PHYTMAC_MSG(index) + MSG_HDR_LEN, 64); +- } ++ for (i = 0 ; i < PHYTMAC_STATIS_REG_NUM; i++) ++ stats[i] = PHYTMAC_READ(pdata, PHYTMAC_OCT_TX + i * 4); + +- for (i = 0, j = 0; i < 44; i++) { ++ for (i = 0, j = 0; i < PHYTMAC_STATIS_REG_NUM; i++) { + if (i == 0 || i == 20) { + val = (u64)stats[i + 1] << 32 | stats[i]; + *p += val; +@@ -384,19 +447,21 @@ static void phytmac_get_hw_stats(struct phytmac *pdata) + } + } + +-static void phytmac_mdio_idle(struct phytmac *pdata) ++static int phytmac_v2_mdio_idle(struct phytmac *pdata) + { + u32 val; ++ int ret; + + /* wait for end of transfer */ +- val = PHYTMAC_READ(pdata, PHYTMAC_NETWORK_STATUS); +- while (!(val & PHYTMAC_BIT(MIDLE))) { +- cpu_relax(); +- val = PHYTMAC_READ(pdata, PHYTMAC_NETWORK_STATUS); +- } ++ ret = readx_poll_timeout(PHYTMAC_READ_NSR, pdata, val, val & PHYTMAC_BIT(MIDLE), ++ 1, PHYTMAC_MDIO_TIMEOUT); ++ if (ret) ++ netdev_err(pdata->ndev, "mdio wait for idle time out!"); ++ ++ return ret; + } + +-static int phytmac_mdio_data_read(struct phytmac *pdata, int mii_id, int regnum, int is_c45) ++static int phytmac_v2_mdio_data_read(struct phytmac *pdata, int mii_id, int regnum, int is_c45) + { + u16 data; + +@@ -407,7 +472,7 @@ static int phytmac_mdio_data_read(struct phytmac *pdata, int mii_id, int regnum, + | PHYTMAC_BITS(REGADDR, (regnum >> 16) & 0x1F) + | PHYTMAC_BITS(VALUE, regnum & 0xFFFF) + | PHYTMAC_BITS(CONST, 2))); +- phytmac_mdio_idle(pdata); ++ phytmac_v2_mdio_idle(pdata); + PHYTMAC_WRITE(pdata, PHYTMAC_MDIO, (PHYTMAC_BITS(CLAUSESEL, PHYTMAC_C45) + | PHYTMAC_BITS(MDCOPS, PHYTMAC_C45_READ) + | PHYTMAC_BITS(PHYADDR, mii_id) +@@ -421,14 +486,14 @@ static int phytmac_mdio_data_read(struct phytmac *pdata, int mii_id, int regnum, + | PHYTMAC_BITS(REGADDR, regnum) + | PHYTMAC_BITS(CONST, 2))); + } +- phytmac_mdio_idle(pdata); ++ phytmac_v2_mdio_idle(pdata); + data = PHYTMAC_READ(pdata, PHYTMAC_MDIO) & 0xffff; +- phytmac_mdio_idle(pdata); ++ phytmac_v2_mdio_idle(pdata); + return data; + } + +-static int phytmac_mdio_data_write(struct phytmac *pdata, int mii_id, +- int regnum, int is_c45, u16 data) ++static int phytmac_v2_mdio_data_write(struct phytmac *pdata, int mii_id, ++ int regnum, int is_c45, u16 data) + { + if (is_c45) { + PHYTMAC_WRITE(pdata, PHYTMAC_MDIO, (PHYTMAC_BITS(CLAUSESEL, PHYTMAC_C45) +@@ -437,7 +502,7 @@ static int phytmac_mdio_data_write(struct phytmac *pdata, int mii_id, + | PHYTMAC_BITS(REGADDR, (regnum >> 16) & 0x1F) + | PHYTMAC_BITS(VALUE, regnum & 0xFFFF) + | PHYTMAC_BITS(CONST, 2))); +- phytmac_mdio_idle(pdata); ++ phytmac_v2_mdio_idle(pdata); + PHYTMAC_WRITE(pdata, PHYTMAC_MDIO, (PHYTMAC_BITS(CLAUSESEL, PHYTMAC_C45) + | PHYTMAC_BITS(MDCOPS, PHYTMAC_C45_WRITE) + | PHYTMAC_BITS(PHYADDR, mii_id) +@@ -452,17 +517,57 @@ static int phytmac_mdio_data_write(struct phytmac *pdata, int mii_id, + | PHYTMAC_BITS(VALUE, data) + | PHYTMAC_BITS(CONST, 2))); + } +- phytmac_mdio_idle(pdata); ++ phytmac_v2_mdio_idle(pdata); + + return 0; + } + +-static int phytmac_powerup_hw(struct phytmac *pdata, int on) ++static int phytmac_v2_powerup_hw(struct phytmac *pdata, int on) + { + u32 status, data0, data1, rdata1; + int ret; ++ acpi_handle handle; ++ union acpi_object args[3]; ++ struct acpi_object_list arg_list = { ++ .pointer = args, ++ .count = ARRAY_SIZE(args), ++ }; ++ acpi_status acpi_sts; ++ unsigned long long rv; ++ ++ if (!(pdata->capacities & PHYTMAC_CAPS_PWCTRL)) { ++ pdata->power_state = on; ++ return 0; ++ } + +- if (pdata->capacities & PHYTMAC_CAPS_LPI) { ++ if (has_acpi_companion(pdata->dev)) { ++#ifdef CONFIG_ACPI ++ handle = ACPI_HANDLE(pdata->dev); ++ ++ netdev_info(pdata->ndev, "set gmac power %s\n", ++ on == PHYTMAC_POWERON ? "on" : "off"); ++ args[0].type = ACPI_TYPE_INTEGER; ++ args[0].integer.value = PHYTMAC_PWCTL_GMAC_ID; ++ args[1].type = ACPI_TYPE_INTEGER; ++ args[1].integer.value = PHYTMAC_PWCTL_DEFAULT_VAL; ++ args[2].type = ACPI_TYPE_INTEGER; ++ args[2].integer.value = PHYTMAC_PWCTL_DEFAULT_VAL; ++ ++ if (on == PHYTMAC_POWERON) { ++ acpi_sts = acpi_evaluate_integer(handle, "PPWO", &arg_list, &rv); ++ if (ACPI_FAILURE(acpi_sts)) ++ netdev_err(pdata->ndev, "NO PPWO Method\n"); ++ if (rv) ++ netdev_err(pdata->ndev, "Failed to power on\n"); ++ } else { ++ acpi_sts = acpi_evaluate_integer(handle, "PPWD", &arg_list, &rv); ++ if (ACPI_FAILURE(acpi_sts)) ++ netdev_err(pdata->ndev, "NO PPWD Method\n"); ++ if (rv) ++ netdev_err(pdata->ndev, "Failed to power off\n"); ++ } ++#endif /* CONFIG_ACPI */ ++ } else { + ret = readx_poll_timeout(PHYTMAC_READ_STAT, pdata, status, !status, + 1, PHYTMAC_TIMEOUT); + if (ret) +@@ -500,10 +605,10 @@ static int phytmac_powerup_hw(struct phytmac *pdata, int on) + rdata1 = PHYTMAC_MHU_READ(pdata, PHYTMAC_MHU_CPP_DATA1); + if (rdata1 == data1) + netdev_err(pdata->ndev, "gmac power %s success, data1 = %x, rdata1=%x\n", +- on ? "up" : "down", data1, rdata1); ++ on == PHYTMAC_POWERON ? "up" : "down", data1, rdata1); + else + netdev_err(pdata->ndev, "gmac power %s failed, data1 = %x, rdata1=%x\n", +- on ? "up" : "down", data1, rdata1); ++ on == PHYTMAC_POWERON ? "up" : "down", data1, rdata1); + } + + pdata->power_state = on; +@@ -511,20 +616,32 @@ static int phytmac_powerup_hw(struct phytmac *pdata, int on) + return 0; + } + +-static int phytmac_set_wake(struct phytmac *pdata, int wake) ++static int phytmac_v2_set_wake(struct phytmac *pdata, int wake) + { + u16 cmd_id, cmd_subid; +- u8 wol = (u8)wake; ++ struct phytmac_wol para; ++ u32 wol_type = 0; ++ ++ if (wake & PHYTMAC_WAKE_MAGIC) ++ wol_type |= PHYTMAC_BIT(MAGIC); ++ if (wake & PHYTMAC_WAKE_ARP) ++ wol_type |= PHYTMAC_BIT(ARP); ++ if (wake & PHYTMAC_WAKE_UCAST) ++ wol_type |= PHYTMAC_BIT(UCAST); ++ if (wake & PHYTMAC_WAKE_MCAST) ++ wol_type |= PHYTMAC_BIT(MCAST); + + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_WOL; +- +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&wol), 1, 1); ++ memset(¶, 0, sizeof(para)); ++ para.wol_type = cpu_to_le32(wol_type); ++ para.wake = (u8)wake; ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); + + return 0; + } + +-static int phytmac_enable_promise(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_promise(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + u8 rxcsum = 0; +@@ -538,12 +655,12 @@ static int phytmac_enable_promise(struct phytmac *pdata, int enable) + rxcsum = 1; + } + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxcsum), 1, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&rxcsum), 1, 1); + + return 0; + } + +-static int phytmac_enable_rxcsum(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_rxcsum(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -553,12 +670,12 @@ static int phytmac_enable_rxcsum(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_RXCSUM; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_enable_txcsum(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_txcsum(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -568,12 +685,12 @@ static int phytmac_enable_txcsum(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_TXCSUM; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_enable_mdio(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_mdio(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -583,12 +700,12 @@ static int phytmac_enable_mdio(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_MDIO; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_enable_autoneg(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_autoneg(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -598,13 +715,13 @@ static int phytmac_enable_autoneg(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_AUTONEG; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + pdata->autoneg = enable; + return 0; + } + +-static int phytmac_enable_pause(struct phytmac *pdata, int enable) ++static int phytmac_v2_enable_pause(struct phytmac *pdata, int enable) + { + u16 cmd_id, cmd_subid; + +@@ -614,12 +731,12 @@ static int phytmac_enable_pause(struct phytmac *pdata, int enable) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_PAUSE; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_enable_network(struct phytmac *pdata, int enable, int rx_tx) ++static int phytmac_v2_enable_network(struct phytmac *pdata, int enable, int rx_tx) + { + u16 cmd_id, cmd_subid; + +@@ -629,12 +746,12 @@ static int phytmac_enable_network(struct phytmac *pdata, int enable, int rx_tx) + else + cmd_subid = PHYTMAC_MSG_CMD_SET_DISABLE_NETWORK; + +- phytmac_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + + return 0; + } + +-static int phytmac_add_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_spec *rx_flow) ++static int phytmac_v2_add_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_spec *rx_flow) + { + struct ethtool_tcpip4_spec *tp4sp_v, *tp4sp_m; + struct phytmac_fdir_info fdir; +@@ -662,19 +779,19 @@ static int phytmac_add_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_ + fdir.srcport_mask = tp4sp_m->psrc; + } + +- fdir.location = rx_flow->location; +- fdir.queue = rx_flow->ring_cookie; ++ fdir.location = (u8)(rx_flow->location); ++ fdir.queue = (u8)(rx_flow->ring_cookie); + + if (fdir.ipsrc_en || fdir.ipdst_en || fdir.port_en) { + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_ADD_FDIR; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&fdir), sizeof(fdir), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&fdir), sizeof(fdir), 1); + } + + return 0; + } + +-static int phytmac_del_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_spec *rx_flow) ++static int phytmac_v2_del_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_spec *rx_flow) + { + struct phytmac_fdir_info fdir; + u16 cmd_id, cmd_subid; +@@ -682,21 +799,21 @@ static int phytmac_del_fdir_entry(struct phytmac *pdata, struct ethtool_rx_flow_ + memset(&fdir, 0, sizeof(fdir)); + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_DEL_FDIR; +- fdir.location = (u8)rx_flow->location; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(&fdir), sizeof(fdir), 1); ++ fdir.location = (u8)(rx_flow->location); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(&fdir), sizeof(fdir), 1); + + return 0; + } + +-static void phytmac_tx_start(struct phytmac_queue *queue) ++static void phytmac_v2_tx_start(struct phytmac_queue *queue) + { + struct phytmac *pdata = queue->pdata; + +- PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_PTR(queue->index), queue->tx_tail); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_PTR(queue->index), queue->tx_tail); + queue->tx_xmit_more = 0; + } + +-static u32 phytmac_get_irq_mask(u32 mask) ++static u32 phytmac_v2_get_irq_mask(u32 mask) + { + u32 value = 0; + +@@ -709,7 +826,7 @@ static u32 phytmac_get_irq_mask(u32 mask) + return value; + } + +-static u32 phytmac_get_irq_status(u32 value) ++static u32 phytmac_v2_get_irq_status(u32 value) + { + u32 status = 0; + +@@ -722,111 +839,124 @@ static u32 phytmac_get_irq_status(u32 value) + return status; + } + +-static void phytmac_enable_irq(struct phytmac *pdata, +- int queue_index, u32 mask) ++static void phytmac_v2_enable_irq(struct phytmac *pdata, ++ int queue_index, u32 mask) + { + u32 value; + +- value = phytmac_get_irq_mask(mask); ++ value = phytmac_v2_get_irq_mask(mask); + PHYTMAC_WRITE(pdata, PHYTMAC_INT_ER(queue_index), value); + } + +-static void phytmac_disable_irq(struct phytmac *pdata, +- int queue_index, u32 mask) ++static void phytmac_v2_disable_irq(struct phytmac *pdata, ++ int queue_index, u32 mask) + { + u32 value; + +- value = phytmac_get_irq_mask(mask); ++ value = phytmac_v2_get_irq_mask(mask); + PHYTMAC_WRITE(pdata, PHYTMAC_INT_DR(queue_index), value); + } + +-static void phytmac_clear_irq(struct phytmac *pdata, +- int queue_index, u32 mask) ++static void phytmac_v2_clear_irq(struct phytmac *pdata, ++ int queue_index, u32 mask) + { + u32 value; + +- value = phytmac_get_irq_mask(mask); ++ value = phytmac_v2_get_irq_mask(mask); + PHYTMAC_WRITE(pdata, PHYTMAC_INT_SR(queue_index), value); + } + +-static unsigned int phytmac_get_irq(struct phytmac *pdata, int queue_index) ++static unsigned int phytmac_v2_get_irq(struct phytmac *pdata, int queue_index) + { + u32 status; + u32 value; + + value = PHYTMAC_READ(pdata, PHYTMAC_INT_SR(queue_index)); +- status = phytmac_get_irq_status(value); ++ status = phytmac_v2_get_irq_status(value); + + return status; + } + +-static void phytmac_interface_config(struct phytmac *pdata, unsigned int mode, +- const struct phylink_link_state *state) ++static void phytmac_v2_interface_config(struct phytmac *pdata, unsigned int mode, ++ const struct phylink_link_state *state) + { + struct phytmac_interface_info para; + u16 cmd_id, cmd_subid; ++ u8 autoneg = 0; ++ ++ if (state->interface == PHY_INTERFACE_MODE_SGMII) { ++ if (mode == MLO_AN_FIXED) ++ autoneg = 0; ++ else ++ autoneg = 1; ++ } ++ ++ if (state->interface == PHY_INTERFACE_MODE_1000BASEX) ++ autoneg = 1; ++ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) ++ autoneg = 0; + + memset(¶, 0, sizeof(para)); + cmd_id = PHYTMAC_MSG_CMD_SET; +- cmd_subid = PHYTMAC_MSG_CMD_SET_MAC_CONFIG; +- para.interface = state->interface; +- para.autoneg = (mode == MLO_AN_FIXED ? 0 : 1); ++ cmd_subid = PHYTMAC_MSG_CMD_SET_INIT_MAC_CONFIG; ++ para.interface = pdata->phytmac_v2_interface; ++ para.autoneg = autoneg; + para.speed = state->speed; + para.duplex = state->duplex; + pdata->autoneg = para.autoneg; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); + } + +-static int phytmac_interface_linkup(struct phytmac *pdata, phy_interface_t interface, +- int speed, int duplex) ++static int phytmac_v2_interface_linkup(struct phytmac *pdata, phy_interface_t interface, ++ int speed, int duplex) + { + struct phytmac_interface_info para; + u16 cmd_id, cmd_subid; + ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ if (speed == SPEED_2500) ++ pdata->autoneg = 0; ++ } ++ + memset(¶, 0, sizeof(para)); + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_MAC_LINK_CONFIG; +- para.interface = interface; ++ para.interface = pdata->phytmac_v2_interface; + para.duplex = duplex; + para.speed = speed; + para.autoneg = pdata->autoneg; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); + + return 0; + } + +-static int phytmac_interface_linkdown(struct phytmac *pdata) ++static int phytmac_v2_interface_linkdown(struct phytmac *pdata) + { + return 0; + } + +-static int phytmac_pcs_linkup(struct phytmac *pdata, phy_interface_t interface, +- int speed, int duplex) ++static int phytmac_v2_pcs_linkup(struct phytmac *pdata, phy_interface_t interface, ++ int speed, int duplex) + { +- struct phytmac_interface_info para; + u16 cmd_id, cmd_subid; + + if (interface == PHY_INTERFACE_MODE_USXGMII || + interface == PHY_INTERFACE_MODE_10GBASER) { +- memset(¶, 0, sizeof(para)); + cmd_id = PHYTMAC_MSG_CMD_SET; + cmd_subid = PHYTMAC_MSG_CMD_SET_PCS_LINK_UP; +- para.interface = interface; +- para.duplex = duplex; +- para.speed = speed; +- para.autoneg = 0; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, NULL, 0, 1); + } + + return 0; + } + +-static int phytmac_pcs_linkdown(struct phytmac *pdata) ++static int phytmac_v2_pcs_linkdown(struct phytmac *pdata) + { + return 0; + } + +-static unsigned int phytmac_pcs_get_link(struct phytmac *pdata, phy_interface_t interface) ++static unsigned int phytmac_v2_pcs_get_link(struct phytmac *pdata, phy_interface_t interface) + { + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX || +@@ -839,8 +969,8 @@ static unsigned int phytmac_pcs_get_link(struct phytmac *pdata, phy_interface_t + return 0; + } + +-static unsigned int phytmac_tx_map_desc(struct phytmac_queue *queue, +- u32 tx_tail, struct packet_info *packet) ++static unsigned int phytmac_v2_tx_map_desc(struct phytmac_queue *queue, ++ u32 tx_tail, struct packet_info *packet) + { + unsigned int i, ctrl; + struct phytmac *pdata = queue->pdata; +@@ -883,8 +1013,8 @@ static unsigned int phytmac_tx_map_desc(struct phytmac_queue *queue, + return 0; + } + +-static void phytmac_init_rx_map_desc(struct phytmac_queue *queue, +- u32 index) ++static void phytmac_v2_init_rx_map_desc(struct phytmac_queue *queue, ++ u32 index) + { + struct phytmac_dma_desc *desc; + +@@ -896,7 +1026,7 @@ static void phytmac_init_rx_map_desc(struct phytmac_queue *queue, + desc->desc0 |= PHYTMAC_BIT(RXUSED); + } + +-static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, u32 index, dma_addr_t addr) ++static unsigned int phytmac_v2_rx_map_desc(struct phytmac_queue *queue, u32 index, dma_addr_t addr) + { + struct phytmac *pdata = queue->pdata; + struct phytmac_dma_desc *desc; +@@ -909,32 +1039,51 @@ static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, u32 index, + desc->desc1 = 0; + desc->desc2 = upper_32_bits(addr); + /* Make newly descriptor to hardware */ +- dma_wmb(); ++ if (!(pdata->capacities & PHYTMAC_CAPS_RXPTR)) ++ dma_wmb(); + desc->desc0 = lower_32_bits(addr); + } else { + desc->desc1 = 0; + /* make newly descriptor to hardware */ +- dma_wmb(); ++ if (!(pdata->capacities & PHYTMAC_CAPS_RXPTR)) ++ dma_wmb(); + desc->desc0 &= ~PHYTMAC_BIT(RXUSED); + } + + return 0; + } + +-static unsigned int phytmac_zero_rx_desc_addr(struct phytmac_dma_desc *desc) ++static unsigned int phytmac_v2_zero_rx_desc_addr(struct phytmac_dma_desc *desc) + { + desc->desc2 = 0; +- desc->desc0 = PHYTMAC_BIT(RXUSED); ++ desc->desc0 = (desc->desc0 & PHYTMAC_BIT(RXTSVALID)) | PHYTMAC_BIT(RXUSED); + + return 0; + } + +-static int phytmac_tx_complete(const struct phytmac_dma_desc *desc) ++static unsigned int phytmac_v2_zero_tx_desc(struct phytmac_dma_desc *desc) ++{ ++ desc->desc2 = 0; ++ desc->desc0 = 0; ++ desc->desc1 &= ~PHYTMAC_BIT(TXUSED); ++ ++ return 0; ++} ++ ++static void phytmac_v2_update_rx_tail(struct phytmac_queue *queue) ++{ ++ struct phytmac *pdata = queue->pdata; ++ ++ if (pdata->capacities & PHYTMAC_CAPS_RXPTR) ++ PHYTMAC_WRITE(pdata, PHYTMAC_RX_PTR(queue->index), queue->rx_head); ++} ++ ++static int phytmac_v2_tx_complete(const struct phytmac_dma_desc *desc) + { + return PHYTMAC_GET_BITS(desc->desc1, TXUSED); + } + +-static bool phytmac_rx_complete(const struct phytmac_dma_desc *desc) ++static bool phytmac_v2_rx_complete(const struct phytmac_dma_desc *desc) + { + dma_addr_t addr; + bool used; +@@ -949,7 +1098,7 @@ static bool phytmac_rx_complete(const struct phytmac_dma_desc *desc) + return false; + } + +-static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_desc *desc) ++static int phytmac_v2_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_desc *desc) + { + if (pdata->capacities & PHYTMAC_CAPS_JUMBO) + return desc->desc1 & PHYTMAC_RXJFRMLEN_MASK; +@@ -957,7 +1106,7 @@ static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_de + return desc->desc1 & PHYTMAC_RXFRMLEN_MASK; + } + +-static bool phytmac_rx_checksum(const struct phytmac_dma_desc *desc) ++static bool phytmac_v2_rx_checksum(const struct phytmac_dma_desc *desc) + { + u32 value = desc->desc1; + u32 check = value >> PHYTMAC_RXCSUM_INDEX & 0x3; +@@ -965,28 +1114,28 @@ static bool phytmac_rx_checksum(const struct phytmac_dma_desc *desc) + return (check == PHYTMAC_RXCSUM_IP_TCP || check == PHYTMAC_RXCSUM_IP_UDP); + } + +-static bool phytmac_rx_single_buffer(const struct phytmac_dma_desc *desc) ++static bool phytmac_v2_rx_single_buffer(const struct phytmac_dma_desc *desc) + { + u32 value = desc->desc1; + + return ((value & PHYTMAC_BIT(RXSOF)) && (value & PHYTMAC_BIT(RXEOF))); + } + +-static bool phytmac_rx_sof(const struct phytmac_dma_desc *desc) ++static bool phytmac_v2_rx_sof(const struct phytmac_dma_desc *desc) + { + u32 value = desc->desc1; + + return (value & PHYTMAC_BIT(RXSOF)); + } + +-static bool phytmac_rx_eof(const struct phytmac_dma_desc *desc) ++static bool phytmac_v2_rx_eof(const struct phytmac_dma_desc *desc) + { + u32 value = desc->desc1; + + return (value & PHYTMAC_BIT(RXEOF)); + } + +-static void phytmac_clear_rx_desc(struct phytmac_queue *queue, int begin, int end) ++static void phytmac_v2_clear_rx_desc(struct phytmac_queue *queue, int begin, int end) + { + unsigned int frag; + unsigned int tmp = end; +@@ -1001,7 +1150,7 @@ static void phytmac_clear_rx_desc(struct phytmac_queue *queue, int begin, int en + } + } + +-static void phytmac_clear_tx_desc(struct phytmac_queue *queue) ++static void phytmac_v2_clear_tx_desc(struct phytmac_queue *queue) + { + struct phytmac *pdata = queue->pdata; + struct phytmac_dma_desc *desc = NULL; +@@ -1018,10 +1167,10 @@ static void phytmac_clear_tx_desc(struct phytmac_queue *queue) + desc->desc1 = PHYTMAC_BIT(TXUSED); + } + desc->desc1 |= PHYTMAC_BIT(TXWRAP); +- PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_PTR(queue->index), queue->tx_tail); ++ PHYTMAC_WRITE(pdata, PHYTMAC_TX_PTR(queue->index), queue->tx_tail); + } + +-static void phytmac_get_time(struct phytmac *pdata, struct timespec64 *ts) ++static void phytmac_v2_get_time(struct phytmac *pdata, struct timespec64 *ts) + { + u32 ns, secl, sech; + +@@ -1033,7 +1182,7 @@ static void phytmac_get_time(struct phytmac *pdata, struct timespec64 *ts) + ts->tv_sec = (((u64)sech << 32) | secl) & TIMER_SEC_MAX_VAL; + } + +-void phytmac_set_time(struct phytmac *pdata, time64_t sec, long nsec) ++static void phytmac_v2_set_time(struct phytmac *pdata, time64_t sec, long nsec) + { + u32 secl, sech; + +@@ -1046,7 +1195,7 @@ void phytmac_set_time(struct phytmac *pdata, time64_t sec, long nsec) + PHYTMAC_WRITE(pdata, PHYTMAC_TIMER_NSEC, nsec); + } + +-void phytmac_clear_time(struct phytmac *pdata) ++static void phytmac_v2_clear_time(struct phytmac *pdata) + { + u32 value; + +@@ -1064,7 +1213,7 @@ void phytmac_clear_time(struct phytmac *pdata) + PHYTMAC_WRITE(pdata, PHYTMAC_TIMER_ADJUST, 0); + } + +-int phytmac_set_tsmode(struct phytmac *pdata, struct ts_ctrl *ctrl) ++static int phytmac_v2_set_tsmode(struct phytmac *pdata, struct ts_ctrl *ctrl) + { + u16 cmd_id, cmd_subid; + struct phytmac_ts_config para; +@@ -1074,12 +1223,12 @@ int phytmac_set_tsmode(struct phytmac *pdata, struct ts_ctrl *ctrl) + para.tx_mode = ctrl->tx_control; + para.rx_mode = ctrl->rx_control; + para.one_step = ctrl->one_step; +- phytmac_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); ++ phytmac_v2_msg_send(pdata, cmd_id, cmd_subid, (void *)(¶), sizeof(para), 1); + + return 0; + } + +-static int phytmac_set_tsincr(struct phytmac *pdata, struct ts_incr *incr) ++static int phytmac_v2_set_tsincr(struct phytmac *pdata, struct ts_incr *incr) + { + u32 value; + +@@ -1090,17 +1239,17 @@ static int phytmac_set_tsincr(struct phytmac *pdata, struct ts_incr *incr) + return 0; + } + +-static void phytmac_ptp_init_hw(struct phytmac *pdata) ++static void phytmac_v2_ptp_init_hw(struct phytmac *pdata) + { + struct timespec64 ts; + + ts = ns_to_timespec64(ktime_to_ns(ktime_get_real())); +- phytmac_set_time(pdata, ts.tv_sec, ts.tv_nsec); ++ phytmac_v2_set_time(pdata, ts.tv_sec, ts.tv_nsec); + +- phytmac_set_tsincr(pdata, &pdata->ts_incr); ++ phytmac_v2_set_tsincr(pdata, &pdata->ts_incr); + } + +-static int phytmac_adjust_fine(struct phytmac *pdata, long ppm, bool negative) ++static int phytmac_v2_adjust_fine(struct phytmac *pdata, long ppm, bool negative) + { + struct ts_incr ts_incr; + u32 tmp; +@@ -1120,22 +1269,25 @@ static int phytmac_adjust_fine(struct phytmac *pdata, long ppm, bool negative) + & ((1 << PHYTMAC_INCR_NSEC_WIDTH) - 1); + ts_incr.sub_ns = adj & ((1 << PHYTMAC_INCR_SNSEC_WIDTH) - 1); + +- phytmac_set_tsincr(pdata, &ts_incr); ++ phytmac_v2_set_tsincr(pdata, &ts_incr); + + return 0; + } + +-int phytmac_adjust_time(struct phytmac *pdata, s64 delta, int neg) ++static int phytmac_v2_adjust_time(struct phytmac *pdata, s64 delta, int neg) + { + u32 adj; + + if (delta > PHYTMAC_ASEC_MAX) { + struct timespec64 now, then; + +- then = ns_to_timespec64(delta); +- phytmac_get_time(pdata, &now); ++ if (neg) ++ then = ns_to_timespec64(-delta); ++ else ++ then = ns_to_timespec64(delta); ++ phytmac_v2_get_time(pdata, &now); + now = timespec64_add(now, then); +- phytmac_set_time(pdata, now.tv_sec, now.tv_nsec); ++ phytmac_v2_set_time(pdata, now.tv_sec, now.tv_nsec); + } else { + adj = (neg << PHYTMAC_AADD_INDEX) | delta; + PHYTMAC_WRITE(pdata, PHYTMAC_TIMER_ADJUST, adj); +@@ -1144,7 +1296,7 @@ int phytmac_adjust_time(struct phytmac *pdata, s64 delta, int neg) + return 0; + } + +-static int phytmac_ts_valid(struct phytmac *pdata, struct phytmac_dma_desc *desc, int direction) ++static int phytmac_v2_ts_valid(struct phytmac *pdata, struct phytmac_dma_desc *desc, int direction) + { + int ts_valid = 0; + +@@ -1155,7 +1307,7 @@ static int phytmac_ts_valid(struct phytmac *pdata, struct phytmac_dma_desc *desc + return ts_valid; + } + +-static void phytmac_get_dma_ts(struct phytmac *pdata, u32 ts_1, u32 ts_2, struct timespec64 *ts) ++static void phytmac_v2_get_dma_ts(struct phytmac *pdata, u32 ts_1, u32 ts_2, struct timespec64 *ts) + { + struct timespec64 ts2; + +@@ -1163,7 +1315,7 @@ static void phytmac_get_dma_ts(struct phytmac *pdata, u32 ts_1, u32 ts_2, struct + PHYTMAC_GET_BITS(ts_1, TS_SECL); + ts->tv_nsec = PHYTMAC_GET_BITS(ts_1, TS_NSEC); + +- phytmac_get_time(pdata, &ts2); ++ phytmac_v2_get_time(pdata, &ts2); + + if (((ts->tv_sec ^ ts2.tv_sec) & (PHYTMAC_TS_SEC_TOP >> 1)) != 0) + ts->tv_sec -= PHYTMAC_TS_SEC_TOP; +@@ -1171,78 +1323,81 @@ static void phytmac_get_dma_ts(struct phytmac *pdata, u32 ts_1, u32 ts_2, struct + ts->tv_sec += (ts2.tv_sec & (~PHYTMAC_TS_SEC_MASK)); + } + +-static unsigned int phytmac_get_ts_rate(struct phytmac *pdata) ++static unsigned int phytmac_v2_get_ts_rate(struct phytmac *pdata) + { + return 300000000; + } + + struct phytmac_hw_if phytmac_2p0_hw = { +- .init_msg_ring = phytmac_init_msg_ring, +- .reset_hw = phytmac_reset_hw, +- .init_hw = phytmac_init_hw, +- .init_ring_hw = phytmac_init_ring_hw, +- .get_feature = phytmac_get_feature_all, +- .get_regs = phytmac_get_regs, +- .get_stats = phytmac_get_hw_stats, +- .set_mac_address = phytmac_set_mac_addr, +- .get_mac_address = phytmac_get_mac_addr, +- .mdio_read = phytmac_mdio_data_read, +- .mdio_write = phytmac_mdio_data_write, +- .poweron = phytmac_powerup_hw, +- .set_wol = phytmac_set_wake, +- .enable_promise = phytmac_enable_promise, +- .enable_multicast = phytmac_enable_multicast, +- .set_hash_table = phytmac_set_mc_hash, +- .enable_rx_csum = phytmac_enable_rxcsum, +- .enable_tx_csum = phytmac_enable_txcsum, +- .enable_mdio_control = phytmac_enable_mdio, +- .enable_autoneg = phytmac_enable_autoneg, +- .enable_pause = phytmac_enable_pause, +- .enable_network = phytmac_enable_network, +- .add_fdir_entry = phytmac_add_fdir_entry, +- .del_fdir_entry = phytmac_del_fdir_entry, ++ .init_msg_ring = phytmac_v2_init_msg_ring, ++ .reset_hw = phytmac_v2_reset_hw, ++ .init_hw = phytmac_v2_init_hw, ++ .init_ring_hw = phytmac_v2_init_ring_hw, ++ .get_feature = phytmac_v2_get_feature_all, ++ .get_regs = phytmac_v2_get_regs, ++ .get_stats = phytmac_v2_get_hw_stats, ++ .set_mac_address = phytmac_v2_set_mac_addr, ++ .get_mac_address = phytmac_v2_get_mac_addr, ++ .mdio_idle = phytmac_v2_mdio_idle, ++ .mdio_read = phytmac_v2_mdio_data_read, ++ .mdio_write = phytmac_v2_mdio_data_write, ++ .poweron = phytmac_v2_powerup_hw, ++ .set_wol = phytmac_v2_set_wake, ++ .enable_promise = phytmac_v2_enable_promise, ++ .enable_multicast = phytmac_v2_enable_multicast, ++ .set_hash_table = phytmac_v2_set_mc_hash, ++ .enable_rx_csum = phytmac_v2_enable_rxcsum, ++ .enable_tx_csum = phytmac_v2_enable_txcsum, ++ .enable_mdio_control = phytmac_v2_enable_mdio, ++ .enable_autoneg = phytmac_v2_enable_autoneg, ++ .enable_pause = phytmac_v2_enable_pause, ++ .enable_network = phytmac_v2_enable_network, ++ .add_fdir_entry = phytmac_v2_add_fdir_entry, ++ .del_fdir_entry = phytmac_v2_del_fdir_entry, + + /* mac config */ +- .mac_config = phytmac_interface_config, +- .mac_linkup = phytmac_interface_linkup, +- .mac_linkdown = phytmac_interface_linkdown, +- .pcs_linkup = phytmac_pcs_linkup, +- .pcs_linkdown = phytmac_pcs_linkdown, +- .get_link = phytmac_pcs_get_link, ++ .mac_config = phytmac_v2_interface_config, ++ .mac_linkup = phytmac_v2_interface_linkup, ++ .mac_linkdown = phytmac_v2_interface_linkdown, ++ .pcs_linkup = phytmac_v2_pcs_linkup, ++ .pcs_linkdown = phytmac_v2_pcs_linkdown, ++ .get_link = phytmac_v2_pcs_get_link, + + /* irq */ +- .enable_irq = phytmac_enable_irq, +- .disable_irq = phytmac_disable_irq, +- .clear_irq = phytmac_clear_irq, +- .get_irq = phytmac_get_irq, ++ .enable_irq = phytmac_v2_enable_irq, ++ .disable_irq = phytmac_v2_disable_irq, ++ .clear_irq = phytmac_v2_clear_irq, ++ .get_irq = phytmac_v2_get_irq, + + /* tx and rx */ +- .tx_map = phytmac_tx_map_desc, +- .transmit = phytmac_tx_start, +- .tx_complete = phytmac_tx_complete, +- .rx_complete = phytmac_rx_complete, +- .get_rx_pkt_len = phytmac_rx_pkt_len, +- .init_rx_map = phytmac_init_rx_map_desc, +- .rx_map = phytmac_rx_map_desc, +- .rx_checksum = phytmac_rx_checksum, +- .rx_single_buffer = phytmac_rx_single_buffer, +- .rx_pkt_start = phytmac_rx_sof, +- .rx_pkt_end = phytmac_rx_eof, +- .clear_rx_desc = phytmac_clear_rx_desc, +- .clear_tx_desc = phytmac_clear_tx_desc, +- .zero_rx_desc_addr = phytmac_zero_rx_desc_addr, ++ .tx_map = phytmac_v2_tx_map_desc, ++ .transmit = phytmac_v2_tx_start, ++ .update_rx_tail = phytmac_v2_update_rx_tail, ++ .tx_complete = phytmac_v2_tx_complete, ++ .rx_complete = phytmac_v2_rx_complete, ++ .get_rx_pkt_len = phytmac_v2_rx_pkt_len, ++ .init_rx_map = phytmac_v2_init_rx_map_desc, ++ .rx_map = phytmac_v2_rx_map_desc, ++ .rx_checksum = phytmac_v2_rx_checksum, ++ .rx_single_buffer = phytmac_v2_rx_single_buffer, ++ .rx_pkt_start = phytmac_v2_rx_sof, ++ .rx_pkt_end = phytmac_v2_rx_eof, ++ .clear_rx_desc = phytmac_v2_clear_rx_desc, ++ .clear_tx_desc = phytmac_v2_clear_tx_desc, ++ .zero_rx_desc_addr = phytmac_v2_zero_rx_desc_addr, ++ .zero_tx_desc = phytmac_v2_zero_tx_desc, + + /* ptp */ +- .init_ts_hw = phytmac_ptp_init_hw, +- .set_time = phytmac_set_time, +- .clear_time = phytmac_clear_time, +- .get_time = phytmac_get_time, +- .set_ts_config = phytmac_set_tsmode, +- .set_incr = phytmac_set_tsincr, +- .adjust_fine = phytmac_adjust_fine, +- .adjust_time = phytmac_adjust_time, +- .ts_valid = phytmac_ts_valid, +- .get_timestamp = phytmac_get_dma_ts, +- .get_ts_rate = phytmac_get_ts_rate, ++ .init_ts_hw = phytmac_v2_ptp_init_hw, ++ .set_time = phytmac_v2_set_time, ++ .clear_time = phytmac_v2_clear_time, ++ .get_time = phytmac_v2_get_time, ++ .set_ts_config = phytmac_v2_set_tsmode, ++ .set_incr = phytmac_v2_set_tsincr, ++ .adjust_fine = phytmac_v2_adjust_fine, ++ .adjust_time = phytmac_v2_adjust_time, ++ .ts_valid = phytmac_v2_ts_valid, ++ .get_timestamp = phytmac_v2_get_dma_ts, ++ .get_ts_rate = phytmac_v2_get_ts_rate, + }; + EXPORT_SYMBOL_GPL(phytmac_2p0_hw); +diff --git a/drivers/net/ethernet/phytium/phytmac_v2.h b/drivers/net/ethernet/phytium/phytmac_v2.h +index 92e4806ac2c1..c9e159b1eb9b 100644 +--- a/drivers/net/ethernet/phytium/phytmac_v2.h ++++ b/drivers/net/ethernet/phytium/phytmac_v2.h +@@ -1,11 +1,16 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ ++/* Copyright(c) 2022 - 2025 Phytium Technology Co., Ltd. */ ++ + #ifndef _PHYTMAC_V2_H + #define _PHYTMAC_V2_H + + extern struct phytmac_hw_if phytmac_2p0_hw; + ++#define PHYTMAC_CMD_PRC_SUCCESS 0x1 + #define PHYTMAC_MSG_SRAM_SIZE 4096 +-#define MSG_HDR_LEN 8 ++#define PHYTMAC_MSG_HDR_LEN 8 ++#define PHYTMAC_MSG_PARA_LEN 56 ++#define PHYTMAC_READ_REG_NUM_MAX (PHYTMAC_MSG_PARA_LEN / sizeof(u32)) + + #define PHYTMAC_TX_MSG_HEAD 0x000 + #define PHYTMAC_TX_MSG_TAIL 0x004 +@@ -13,6 +18,7 @@ extern struct phytmac_hw_if phytmac_2p0_hw; + #define PHYTMAC_RX_MSG_TAIL 0x00c + #define PHYTMAC_MSG_IMR 0x020 + #define PHYTMAC_MSG_ISR 0x02c ++#define PHYTMAC_TAILPTR_ENABLE 0x038 + + #define PHYTMAC_SIZE 0x0048 + #define PHYTMAC_NETWORK_STATUS 0x0240 +@@ -25,7 +31,8 @@ extern struct phytmac_hw_if phytmac_2p0_hw; + #define PHYTMAC_TIMER_SEC 0x0258 + #define PHYTMAC_TIMER_NSEC 0x025c + #define PHYTMAC_TIMER_ADJUST 0x0260 +-#define PHYTMAC_MSG(i) (((i) - 1) * 0x48) ++#define PHYTMAC_MSG(i) ((i) * sizeof(struct phytmac_msg_info)) ++#define PHYTMAC_OCT_TX 0x400 + + #define PHYTMAC_MODULE_ID_GMAC 0x60 + #define PHYTMAC_FLAGS_MSG_COMP 0x1 +@@ -39,6 +46,12 @@ extern struct phytmac_hw_if phytmac_2p0_hw; + #define PHYTMAC_MSG_COMPLETE_INDEX 0 + #define PHYTMAC_MSG_COMPLETE_WIDTH 1 + ++/* Bitfields in PHYTMAC_TAILPTR_ENABLE */ ++#define PHYTMAC_TXTAIL_EN_INDEX 0 /* Enable tx tail */ ++#define PHYTMAC_TXTAIL_EN_WIDTH 1 ++#define PHYTMAC_RXTAIL_EN_INDEX 16 /* Enable rx tail */ ++#define PHYTMAC_RXTAIL_EN_WIDTH 1 ++ + /* Bitfields in PHYTMAC_SIZE */ + #define PHYTMAC_MEM_SIZE_INDEX 0 + #define PHYTMAC_MEM_SIZE_WIDTH 4 +@@ -83,7 +96,8 @@ extern struct phytmac_hw_if phytmac_2p0_hw; + #define TIMER_SEC_MAX_VAL (((u64)1 << PHYTMAC_TIMER_SEC_WIDTH) - 1) + #define TIMER_NSEC_MAX_VAL ((1 << PHYTMAC_TIMER_NSEC_WIDTH) - 1) + +-#define PHYTMAC_TAIL_PTR(i) (0x0100 + ((i) * 4)) ++#define PHYTMAC_TX_PTR(i) (0x0100 + ((i) * 4)) ++#define PHYTMAC_RX_PTR(i) (0x0030 + ((i) * 4)) + #define PHYTMAC_INT_ER(i) (0x0140 + ((i) * 4)) + #define PHYTMAC_INT_DR(i) (0x0180 + ((i) * 4)) + #define PHYTMAC_INT_MR(i) (0x01c0 + ((i) * 4)) +@@ -200,15 +214,42 @@ extern struct phytmac_hw_if phytmac_2p0_hw; + #define PHYTMAC_TS_SEC_MASK 0x3f + #define PHYTMAC_TS_SEC_TOP 0x40 + ++/* WOL register */ ++#define PHYTMAC_ARP_IP_INDEX 0 ++#define PHYTMAC_ARP_IP_WIDTH 16 ++#define PHYTMAC_MAGIC_INDEX 16 ++#define PHYTMAC_MAGIC_WIDTH 1 ++#define PHYTMAC_ARP_INDEX 17 ++#define PHYTMAC_ARP_WIDTH 1 ++#define PHYTMAC_UCAST_INDEX 18 ++#define PHYTMAC_UCAST_WIDTH 1 ++#define PHYTMAC_MCAST_INDEX 19 ++#define PHYTMAC_MCAST_WIDTH 1 ++ + #define HW_DMA_CAP_64B 0x1 + #define HW_DMA_CAP_CSUM 0x2 + #define HW_DMA_CAP_PTP 0x4 +-#define HW_DMA_CAP_DDW64 0x8 +-#define HW_DMA_CAP_DDW128 0x10 ++#define HW_DMA_CAP_DDW32 0x8 ++#define HW_DMA_CAP_DDW64 0x10 ++#define HW_DMA_CAP_DDW128 0x20 + ++#define PHYTMAC_DBW32 1 + #define PHYTMAC_DBW64 2 + #define PHYTMAC_DBW128 4 + ++#define PHYTMAC_CLK_DIV8 0 ++#define PHYTMAC_CLK_DIV16 1 ++#define PHYTMAC_CLK_DIV32 2 ++#define PHYTMAC_CLK_DIV48 3 ++#define PHYTMAC_CLK_DIV64 4 ++#define PHYTMAC_CLK_DIV96 5 ++#define PHYTMAC_CLK_DIV128 6 ++#define PHYTMAC_CLK_DIV224 7 ++ ++#define PHYTMAC_RETRY_TIMES 50000 ++ ++#define PHYTMAC_READ_NSR(pdata) PHYTMAC_READ(pdata, PHYTMAC_NETWORK_STATUS) ++ + enum phytmac_msg_cmd_id { + PHYTMAC_MSG_CMD_DEFAULT = 0, + PHYTMAC_MSG_CMD_SET, +@@ -218,7 +259,7 @@ enum phytmac_msg_cmd_id { + }; + + enum phytmac_default_subid { +- PHYTMAC_MSG_CMD_DEFAULT_RESET_HW = 0, ++ PHYTMAC_MSG_CMD_DEFAULT_RESET_HW = 1, + PHYTMAC_MSG_CMD_DEFAULT_RESET_TX_QUEUE, + PHYTMAC_MSG_CMD_DEFAULT_RESET_RX_QUEUE, + }; +@@ -228,7 +269,7 @@ enum phytmac_set_subid { + PHYTMAC_MSG_CMD_SET_INIT_RING = 1, + PHYTMAC_MSG_CMD_SET_INIT_TX_RING = 2, + PHYTMAC_MSG_CMD_SET_INIT_RX_RING = 3, +- PHYTMAC_MSG_CMD_SET_MAC_CONFIG = 4, ++ PHYTMAC_MSG_CMD_SET_INIT_MAC_CONFIG = 4, + PHYTMAC_MSG_CMD_SET_ADDR = 5, + PHYTMAC_MSG_CMD_SET_DMA_RX_BUFSIZE = 6, + PHYTMAC_MSG_CMD_SET_DMA = 7, +@@ -269,6 +310,13 @@ enum phytmac_set_subid { + PHYTMAC_MSG_CMD_SET_DISABLE_AUTONEG = 42, + PHYTMAC_MSG_CMD_SET_RX_DATA_OFFSET = 43, + PHYTMAC_MSG_CMD_SET_WOL = 44, ++ PHYTMAC_MSG_CMD_SET_ENABLE_RSC = 45, ++ PHYTMAC_MSG_CMD_SET_DISABLE_RSC = 46, ++ PHYTMAC_MSG_CMD_SET_ENABLE_TX_START = 47, ++ PHYTMAC_MSG_CMD_SET_ENABLE_PCS_RESET = 48, ++ PHYTMAC_MSG_CMD_SET_DISABLE_PCS_RESET = 49, ++ PHYTMAC_MSG_CMD_SET_MDC = 50, ++ PHYTMAC_MSG_CMD_SET_OUTSTANDING = 51, + }; + + enum phytmac_get_subid { +@@ -278,6 +326,8 @@ enum phytmac_get_subid { + PHYTMAC_MSG_CMD_GET_BD_PREFETCH, + PHYTMAC_MSG_CMD_GET_STATS, + PHYTMAC_MSG_CMD_GET_REG_READ, ++ PHYTMAC_MSG_CMD_GET_RX_FLOW, ++ PHYTMAC_MSG_CMD_GET_REGS_FOR_ETHTOOL, + }; + + struct phytmac_interface_info { +@@ -292,6 +342,11 @@ struct phytmac_mc_info { + u32 mc_top; + } __packed; + ++struct phytmac_reg_info { ++ u32 offset; ++ u16 regnum; ++} __packed; ++ + struct phytmac_fdir_info { + u32 ip4src; + u32 ip4dst; +@@ -351,12 +406,36 @@ struct phytmac_feature { + u8 max_rx_fs; + } __packed; + ++struct phytmac_wol { ++ u32 wol_type; ++ u8 wake; ++} __packed; ++ + struct phytmac_msg_info { +- u16 module_id; +- u16 cmd_id; +- u16 cmd_subid; +- u16 flags; +- u8 para[64]; ++ u8 reserved; ++ u8 seq; ++ u8 cmd_type; ++ u8 cmd_subid; ++ u16 len; ++ u8 status1; ++ u8 status0; ++ u8 para[PHYTMAC_MSG_PARA_LEN]; ++} __packed; ++ ++struct phytmac_ots_config { ++ u32 axi_rd; ++ u32 axi_wr; ++ u8 queuenum; + } __packed; + ++struct phytmac_ethtool_reg { ++ u8 interface; ++ u8 cnt; ++} __packed; ++ ++static inline unsigned int phytmac_v2_tx_ring_wrap(struct phytmac *pdata, unsigned int index) ++{ ++ return index & (pdata->msg_ring.tx_msg_ring_size - 1); ++} ++ + #endif +diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c +index 31a64698beba..79ea717672e8 100755 +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -6,18 +6,18 @@ + * + * Author: yinghong.zhang + * +- * Copyright (c) 2019 Motorcomm, Inc. ++ * Copyright (c) 2024 Motorcomm, Inc. + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * +- * Support : Motorcomm Phys: +- * Giga phys: yt8511, yt8521, yt8531, yt8614, yt8618 +- * 100/10 Phys : yt8512, yt8512b, yt8510 +- * Automotive 100Mb Phys : yt8010 +- * Automotive 100/10 hyper range Phys: yt8510 ++ * Support Motorcomm Phys: ++ * Giga phys: yt8511, yt8521, yt8531, yt8543, yt8614, yt8618 ++ * 100/10M Phys: yt8510, yt8512, yt8522 ++ * Automotive 100M Phys: yt8010 ++ * Automotive 1000M Phys: yt8011 + */ + + #include +@@ -31,122 +31,136 @@ + #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) + #endif + +-/* for wol feature, 20210604 */ ++/* for wol feature */ + #include + +-#define YT_LINUX_MAJOR 2 +-#define YT_LINUX_MINOR 2 +-#define YT_LINUX_SUBVERSION 8661 +-#define YT_LINUX_VERSIONID "2.2.8661" +- +-/******************************************** +- **** configuration section begin ***********/ ++#include ++#define MODULE_NAME "yt" ++#define PHYDRV_VER "phydrv_ver" ++static struct dentry *dir; ++#include ++#define YTPHY_LINUX_VERSION "2.2.42319" + ++/**************** configuration section begin ************/ + /* if system depends on ethernet packet to restore from sleep, + * please define this macro to 1 otherwise, define it to 0. + */ +-#define SYS_WAKEUP_BASED_ON_ETH_PKT 0 ++#define SYS_WAKEUP_BASED_ON_ETH_PKT 1 + + /* to enable system WOL feature of phy, please define this macro to 1 + * otherwise, define it to 0. + */ +-#define YTPHY_WOL_FEATURE_ENABLE 0 ++#define YTPHY_WOL_FEATURE_ENABLE 0 + + /* some GMAC need clock input from PHY, for eg., 125M, + * please enable this macro + * by degault, it is set to 0 + * NOTE: this macro will need macro SYS_WAKEUP_BASED_ON_ETH_PKT to set to 1 + */ +-#define GMAC_CLOCK_INPUT_NEEDED 0 +- +-/* the max number of yt8521 chip on pcb board +- * the most case is only 1 chip per board, but +- * by default, we support up to 8. +- */ +-#define YTPHY_BOARD_MAX_NUM_OF_CHIP_8521 8 +-#define YTPHY_BOARD_MAX_NUM_OF_CHIP_8614 4 ++#define GMAC_CLOCK_INPUT_NEEDED 0 + + /* for YT8531 package A xtal init config */ +-#define YTPHY8531A_XTAL_INIT (0) ++#define YTPHY8531A_XTAL_INIT (0) + +-/**** configuration section end *********** +- ******************************************/ ++/**** configuration section end ************/ + + /* no need to change below */ +-#define MOTORCOMM_PHY_ID_MASK 0x00000fff +-#define MOTORCOMM_PHY_ID_8531_MASK 0xffffffff +-#define MOTORCOMM_MPHY_ID_MASK 0x0000ffff +-#define MOTORCOMM_MPHY_ID_MASK_8614 0xffffffff +-#define MOTORCOMM_PHY_ID_MASK_8821 0xffffffff +- +-#define PHY_ID_YT8010 0x00000309 +-#define PHY_ID_YT8010AS 0x4f51eb19 +-#define PHY_ID_YT8510 0x00000109 +-#define PHY_ID_YT8511 0x0000010a +-#define PHY_ID_YT8512 0x00000118 +-#define PHY_ID_YT8512B 0x00000128 +-#define PHY_ID_YT8521 0x0000011a +-#define PHY_ID_YT8531S 0x4f51e91a +-#define PHY_ID_YT8531 0x4f51e91b +-#define PHY_ID_YT8614 0x4F51E899 +-#define PHY_ID_YT8618 0x0000e889 +-#define PHY_ID_YT8821 0x4f51ea10 +- +-#define REG_PHY_SPEC_STATUS 0x11 +-#define REG_DEBUG_ADDR_OFFSET 0x1e +-#define REG_DEBUG_DATA 0x1f +- +-#define YT8512_EXTREG_LED0 0x40c0 +-#define YT8512_EXTREG_LED1 0x40c3 +- +-#define YT8512_EXTREG_SLEEP_CONTROL1 0x2027 +- +-#define YT_SOFTWARE_RESET 0x8000 +- +-#define YT8512_LED0_ACT_BLK_IND 0x1000 +-#define YT8512_LED0_DIS_LED_AN_TRY 0x0001 +-#define YT8512_LED0_BT_BLK_EN 0x0002 +-#define YT8512_LED0_HT_BLK_EN 0x0004 +-#define YT8512_LED0_COL_BLK_EN 0x0008 +-#define YT8512_LED0_BT_ON_EN 0x0010 +-#define YT8512_LED1_BT_ON_EN 0x0010 +-#define YT8512_LED1_TXACT_BLK_EN 0x0100 +-#define YT8512_LED1_RXACT_BLK_EN 0x0200 +-#define YT8512_SPEED_MODE 0xc000 +-#define YT8512_DUPLEX 0x2000 +- +-#define YT8512_SPEED_MODE_BIT 14 +-#define YT8512_DUPLEX_BIT 13 +-#define YT8512_EN_SLEEP_SW_BIT 15 +- +-#define YT8521_EXTREG_SLEEP_CONTROL1 0x27 +-#define YT8521_EN_SLEEP_SW_BIT 15 +- +-#define YT8521_SPEED_MODE 0xc000 +-#define YT8521_DUPLEX 0x2000 +-#define YT8521_SPEED_MODE_BIT 14 +-#define YT8521_DUPLEX_BIT 13 +-#define YT8521_LINK_STATUS_BIT 10 ++#define MOTORCOMM_PHY_ID_MASK 0xffffffff ++ ++#define PHY_ID_YT8010 0x00000309 ++#define PHY_ID_YT8010AS 0x4f51eb19 ++#define PHY_ID_YT8011 0x4f51eb01 ++#define PHY_ID_YT8510 0x00000109 ++#define PHY_ID_YT8511 0x0000010a ++#define PHY_ID_YT8512 0x00000128 ++#define PHY_ID_YT8522 0x4f51e928 ++#define PHY_ID_YT8521 0x0000011a ++#define PHY_ID_YT8531S 0x4f51e91a ++#define PHY_ID_YT8531 0x4f51e91b ++/* YT8543 phy driver disable(default) */ ++/* #define YTPHY_YT8543_ENABLE */ ++#ifdef YTPHY_YT8543_ENABLE ++#define PHY_ID_YT8543 0x0008011b ++#endif ++#define PHY_ID_YT8614 0x4f51e899 ++#define PHY_ID_YT8614Q 0x4f51e8a9 ++#define PHY_ID_YT8618 0x4f51e889 ++#define PHY_ID_YT8821 0x4f51ea19 ++ ++#define REG_PHY_SPEC_STATUS 0x11 ++#define REG_DEBUG_ADDR_OFFSET 0x1e ++#define REG_DEBUG_DATA 0x1f ++#define REG_MII_MMD_CTRL 0x0D ++#define REG_MII_MMD_DATA 0x0E ++ ++#define YT8512_EXTREG_LED0 0x40c0 ++#define YT8512_EXTREG_LED1 0x40c3 ++ ++#define YT8512_EXTREG_SLEEP_CONTROL1 0x2027 ++#define YT8512_EXTENDED_COMBO_CONTROL1 0x4000 ++#define YT8512_10BT_DEBUG_LPBKS 0x200A ++ ++#define YT_SOFTWARE_RESET 0x8000 ++ ++#define YT8512_LED0_ACT_BLK_IND 0x1000 ++#define YT8512_LED0_DIS_LED_AN_TRY 0x0001 ++#define YT8512_LED0_BT_BLK_EN 0x0002 ++#define YT8512_LED0_HT_BLK_EN 0x0004 ++#define YT8512_LED0_COL_BLK_EN 0x0008 ++#define YT8512_LED0_BT_ON_EN 0x0010 ++#define YT8512_LED1_BT_ON_EN 0x0010 ++#define YT8512_LED1_TXACT_BLK_EN 0x0100 ++#define YT8512_LED1_RXACT_BLK_EN 0x0200 ++#define YT8512_EN_SLEEP_SW_BIT 15 ++ ++#define YT8522_TX_CLK_DELAY 0x4210 ++#define YT8522_ANAGLOG_IF_CTRL 0x4008 ++#define YT8522_DAC_CTRL 0x2057 ++#define YT8522_INTERPOLATOR_FILTER_1 0x14 ++#define YT8522_INTERPOLATOR_FILTER_2 0x15 ++#define YT8522_EXTENDED_COMBO_CTRL_1 0x4000 ++#define YT8522_TX_DELAY_CONTROL 0x19 ++#define YT8522_EXTENDED_PAD_CONTROL 0x4001 ++ ++#define YT8521_EXTREG_SLEEP_CONTROL1 0x27 ++#define YT8521_EN_SLEEP_SW_BIT 15 ++ ++#define YTXXXX_SPEED_MODE 0xc000 ++#define YTXXXX_DUPLEX 0x2000 ++#define YTXXXX_SPEED_MODE_BIT 14 ++#define YTXXXX_DUPLEX_BIT 13 ++#define YTXXXX_AUTO_NEGOTIATION_BIT 12 ++#define YTXXXX_ASYMMETRIC_PAUSE_BIT 11 ++#define YTXXXX_PAUSE_BIT 10 ++#define YTXXXX_LINK_STATUS_BIT 10 ++ ++#define YT8821_SDS_ASYMMETRIC_PAUSE_BIT 8 ++#define YT8821_SDS_PAUSE_BIT 7 + + /* based on yt8521 wol feature config register */ +-#define YTPHY_UTP_INTR_REG 0x12 ++#define YTPHY_UTP_INTR_REG 0x12 + /* WOL Feature Event Interrupt Enable */ +-#define YTPHY_WOL_FEATURE_INTR BIT(6) ++#define YTPHY_WOL_FEATURE_INTR BIT(6) + + /* Magic Packet MAC address registers */ +-#define YTPHY_WOL_FEATURE_MACADDR2_4_MAGIC_PACKET 0xa007 +-#define YTPHY_WOL_FEATURE_MACADDR1_4_MAGIC_PACKET 0xa008 +-#define YTPHY_WOL_FEATURE_MACADDR0_4_MAGIC_PACKET 0xa009 ++#define YTPHY_WOL_FEATURE_MACADDR2_4_MAGIC_PACKET 0xa007 ++#define YTPHY_WOL_FEATURE_MACADDR1_4_MAGIC_PACKET 0xa008 ++#define YTPHY_WOL_FEATURE_MACADDR0_4_MAGIC_PACKET 0xa009 ++ ++#define YTPHY_WOL_FEATURE_REG_CFG 0xa00a ++#define YTPHY_WOL_FEATURE_TYPE_CFG BIT(0) ++#define YTPHY_WOL_FEATURE_ENABLE_CFG BIT(3) ++#define YTPHY_WOL_FEATURE_INTR_SEL_CFG BIT(6) ++#define YTPHY_WOL_FEATURE_WIDTH1_CFG BIT(1) ++#define YTPHY_WOL_FEATURE_WIDTH2_CFG BIT(2) + +-#define YTPHY_WOL_FEATURE_REG_CFG 0xa00a +-#define YTPHY_WOL_FEATURE_TYPE_CFG BIT(0) /* WOL TYPE Config */ +-#define YTPHY_WOL_FEATURE_ENABLE_CFG BIT(3) /* WOL Enable Config */ +-#define YTPHY_WOL_FEATURE_INTR_SEL_CFG BIT(6) /* WOL Event Interrupt Enable Config */ +-#define YTPHY_WOL_FEATURE_WIDTH1_CFG BIT(1) /* WOL Pulse Width Config */ +-#define YTPHY_WOL_FEATURE_WIDTH2_CFG BIT(2) /* WOL Pulse Width Config */ ++#define YTPHY_REG_SPACE_UTP 0 ++#define YTPHY_REG_SPACE_FIBER 2 + +-#define YTPHY_REG_SPACE_UTP 0 +-#define YTPHY_REG_SPACE_FIBER 2 ++#define YTPHY_REG_SMI_MUX 0xa000 ++#define YT8614_REG_SPACE_UTP 0 ++#define YT8614_REG_SPACE_QSGMII 2 ++#define YT8614_REG_SPACE_SGMII 3 + + enum ytphy_wol_feature_trigger_type_e { + YTPHY_WOL_FEATURE_PULSE_TRIGGER, +@@ -170,34 +184,22 @@ struct ytphy_wol_feature_cfg { + + #if (YTPHY_WOL_FEATURE_ENABLE) + #undef SYS_WAKEUP_BASED_ON_ETH_PKT +-#define SYS_WAKEUP_BASED_ON_ETH_PKT 1 ++#define SYS_WAKEUP_BASED_ON_ETH_PKT 1 + #endif + +-/* YT8521 polling mode */ +-#define YT8521_PHY_MODE_FIBER 1 //fiber mode only +-#define YT8521_PHY_MODE_UTP 2 //utp mode only +-#define YT8521_PHY_MODE_POLL 3 //fiber and utp, poll mode +- +-/* below are for bitmap */ +-#define YT_PHY_MODE_FIBER 1 //fiber/sgmii mode only +-#define YT_PHY_MODE_UTP 2 //utp mode only +-#define YT_PHY_MODE_QSGMII 4 //qsgmii mode only +-#define YT_PHY_MODE_POLL (YT_PHY_MODE_FIBER | YT_PHY_MODE_UTP | YT_PHY_MODE_QSGMII) //qsgmii, fiber/sgmii and utp, poll mode ++struct yt8xxx_priv { ++ u8 polling_mode; ++ u8 chip_mode; ++}; + +-/* support automatically check polling mode for yt8521 +- * for Fiber only system, please define YT8521_PHY_MODE_CURR 1 +- * for UTP only system, please define YT8521_PHY_MODE_CURR 2 +- * for combo system, please define YT8521_PHY_MODE_CURR 3 +- */ +-#define YTPHY_861X_ABC_VER 0 +-#if (YTPHY_861X_ABC_VER) +-static int yt8614_get_port_from_phydev(struct phy_device *phydev); +-#endif +-static int yt8521_hw_strap_polling(struct phy_device *phydev); +-static int yt8614_hw_strap_polling(struct phy_device *phydev); +-#define YT8521_PHY_MODE_CURR yt8521_hw_strap_polling(phydev) +-#define YT8614_PHY_MODE_CURR yt8614_hw_strap_polling(phydev) ++/* polling mode */ ++#define YT_PHY_MODE_FIBER 1 /* fiber mode only */ ++#define YT_PHY_MODE_UTP 2 /* utp mode only */ ++#define YT_PHY_MODE_POLL (YT_PHY_MODE_FIBER | YT_PHY_MODE_UTP) + ++static int ytxxxx_soft_reset(struct phy_device *phydev); ++static int yt861x_soft_reset_paged(struct phy_device *phydev, int reg_space); ++static int yt861x_aneg_done_paged(struct phy_device *phydev, int reg_space); + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) + static int ytphy_config_init(struct phy_device *phydev) + { +@@ -257,6 +259,21 @@ static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val) + } + #endif + ++static int __ytphy_read_ext(struct phy_device *phydev, u32 regnum) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_read(phydev, REG_DEBUG_DATA); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static int ytphy_read_ext(struct phy_device *phydev, u32 regnum) + { + int ret; +@@ -272,6 +289,7 @@ static int ytphy_read_ext(struct phy_device *phydev, u32 regnum) + + err_handle: + phy_unlock_mdio_bus(phydev); ++ + return ret; + } + +@@ -290,6 +308,84 @@ static int ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val) + + err_handle: + phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++static int __ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, REG_DEBUG_DATA, val); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++__attribute__((unused)) static int ytphy_read_mmd(struct phy_device* phydev, ++ u16 device, u16 reg) ++{ ++ int val; ++ ++ phy_lock_mdio_bus(phydev); ++ ++ __phy_write(phydev, REG_MII_MMD_CTRL, device); ++ __phy_write(phydev, REG_MII_MMD_DATA, reg); ++ __phy_write(phydev, REG_MII_MMD_CTRL, device | 0x4000); ++ val = __phy_read(phydev, REG_MII_MMD_DATA); ++ if (val < 0) { ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ dev_err(&phydev->dev, "error read mmd device(%u) reg (%u)\n", ++ device, reg); ++#else ++ dev_err(&phydev->mdio.dev, ++ "error read mmd device(%u) reg (%u)\n", device, reg); ++#endif ++ ++ goto err_handle; ++ } ++ ++err_handle: ++ phy_unlock_mdio_bus(phydev); ++ ++ return val; ++} ++ ++__attribute__((unused)) static int ytphy_write_mmd(struct phy_device* phydev, ++ u16 device, u16 reg, ++ u16 value) ++{ ++ int ret = 0; ++ ++ phy_lock_mdio_bus(phydev); ++ ++ __phy_write(phydev, REG_MII_MMD_CTRL, device); ++ __phy_write(phydev, REG_MII_MMD_DATA, reg); ++ __phy_write(phydev, REG_MII_MMD_CTRL, device | 0x4000); ++ __phy_write(phydev, REG_MII_MMD_DATA, value); ++ ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++static int __ytphy_soft_reset(struct phy_device *phydev) ++{ ++ int ret = 0, val = 0; ++ ++ val = __phy_read(phydev, MII_BMCR); ++ if (val < 0) ++ return val; ++ ++ ret = __phy_write(phydev, MII_BMCR, val | BMCR_RESET); ++ if (ret < 0) ++ return ret; ++ + return ret; + } + +@@ -308,7 +404,6 @@ static int ytphy_soft_reset(struct phy_device *phydev) + return ret; + } + +- + #if (YTPHY8531A_XTAL_INIT) + static int yt8531a_xtal_init(struct phy_device *phydev) + { +@@ -340,16 +435,14 @@ static int yt8531a_xtal_init(struct phy_device *phydev) + } + #endif + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +-#else +-int yt8010_soft_reset(struct phy_device *phydev) ++static int yt8010_soft_reset(struct phy_device *phydev) + { + ytphy_soft_reset(phydev); + + return 0; + } + +-int yt8010AS_soft_reset(struct phy_device *phydev) ++static int yt8010AS_soft_reset(struct phy_device *phydev) + { + int ret = 0; + +@@ -369,10 +462,9 @@ int yt8010AS_soft_reset(struct phy_device *phydev) + + return 0; + } +-#endif + + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +-int yt8010_aneg_done(struct phy_device *phydev) ++static int yt8010_aneg_done(struct phy_device *phydev) + { + int val = 0; + +@@ -383,9 +475,31 @@ int yt8010_aneg_done(struct phy_device *phydev) + } + #endif + ++static int yt8010_config_init(struct phy_device *phydev) ++{ ++ int val; ++ ++ phydev->autoneg = AUTONEG_DISABLE; ++ ++ ytphy_write_ext(phydev, 0x1023, 0xfc00); ++ ytphy_write_ext(phydev, 0x101d, 0x12c0); ++ val = ytphy_read_ext(phydev, 0x1000); ++ val &= ~(1 << 7); ++ ytphy_write_ext(phydev, 0x1000, val); ++ ytphy_write_ext(phydev, 0x101d, 0x12c0); ++ ytphy_write_ext(phydev, 0x101e, 0x1900); ++ ytphy_write_ext(phydev, 0x101f, 0x1900); ++ ytphy_write_ext(phydev, 0x4083, 0x4327); ++ ytphy_write_ext(phydev, 0x4082, 0xc20); ++ ytphy_soft_reset(phydev); ++ ++ return 0; ++} ++ + static int yt8010_config_aneg(struct phy_device *phydev) + { + phydev->speed = SPEED_100; ++ + return 0; + } + +@@ -408,14 +522,262 @@ static int yt8010AS_config_init(struct phy_device *phydev) + { + phydev->autoneg = AUTONEG_DISABLE; + ++ ytphy_write_ext(phydev, 0x1009, 0x0); ++ ++ yt8010AS_soft_reset(phydev); ++ + return 0; + } + +-static int yt8512_led_init(struct phy_device *phydev) ++static int yt8011_probe(struct phy_device *phydev) ++{ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ struct device *dev = &phydev->dev; ++#else ++ struct device *dev = &phydev->mdio.dev; ++#endif ++ struct yt8xxx_priv *priv; ++ int chip_config; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ /* ext reg 0x9030 bit0 ++ * 0 = chip works in RGMII mode; 1 = chip works in SGMII mode ++ */ ++ chip_config = ytphy_read_ext(phydev, 0x9030); ++ priv->chip_mode = chip_config & 0x1; ++ ++ return 0; ++} ++ ++static int yt8011_soft_reset(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ ++ /* utp */ ++ ytphy_write_ext(phydev, 0x9000, 0x0); ++ ytphy_soft_reset(phydev); ++ ++ if (priv->chip_mode) { /* sgmii */ ++ ytphy_write_ext(phydev, 0x9000, 0x8000); ++ ytphy_soft_reset(phydev); ++ ++ /* restore utp space */ ++ ytphy_write_ext(phydev, 0x9000, 0x0); ++ } ++ ++ return 0; ++} ++ ++static int yt8011_config_aneg(struct phy_device *phydev) ++{ ++ phydev->speed = SPEED_1000; ++ ++ return 0; ++} ++ ++#if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) ++static int yt8011_aneg_done(struct phy_device *phydev) ++{ ++ int link_utp = 0; ++ ++ /* UTP */ ++ ytphy_write_ext(phydev, 0x9000, 0); ++ link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & ++ (BIT(YTXXXX_LINK_STATUS_BIT))); ++ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_utp: %d\n", ++ __func__, phydev->addr, link_utp); ++#else ++ netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_utp: %d\n", ++ __func__, phydev->mdio.addr, link_utp); ++#endif ++ ++ return !!(link_utp); ++} ++#endif ++ ++/* #define YT8011_RGMII_DVDDIO_3V3 */ ++/* #define YT8011_RGMII_DVDDIO_2V5 */ ++/* #define YT8011_RGMII_DVDDIO_1V8 */ ++static int yt8011_config_init(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ ++ phydev->autoneg = AUTONEG_DISABLE; ++ ++ /* UTP */ ++ ytphy_write_ext(phydev, 0x9000, 0x0); ++ ++ ytphy_write_ext(phydev, 0x1008, 0x2119); ++ ytphy_write_ext(phydev, 0x1092, 0x712); ++ ytphy_write_ext(phydev, 0x90bc, 0x6661); ++ ytphy_write_ext(phydev, 0x90b9, 0x620b); ++ ytphy_write_ext(phydev, 0x2001, 0x6418); ++ ytphy_write_ext(phydev, 0x1019, 0x3712); ++ ytphy_write_ext(phydev, 0x101a, 0x3713); ++ ytphy_write_ext(phydev, 0x2015, 0x1012); ++ ytphy_write_ext(phydev, 0x2005, 0x810); ++ ytphy_write_ext(phydev, 0x2013, 0xff06); ++ ytphy_write_ext(phydev, 0x1053, 0xf); ++ ytphy_write_ext(phydev, 0x105e, 0xa46c); ++ ytphy_write_ext(phydev, 0x1088, 0x002b); ++ ytphy_write_ext(phydev, 0x1088, 0x002b); ++ ytphy_write_ext(phydev, 0x1088, 0xb); ++ ytphy_write_ext(phydev, 0x3008, 0x143); ++ ytphy_write_ext(phydev, 0x3009, 0x1918); ++ ytphy_write_ext(phydev, 0x9095, 0x1a1a); ++ ytphy_write_ext(phydev, 0x9096, 0x1a10); ++ ytphy_write_ext(phydev, 0x9097, 0x101a); ++ ytphy_write_ext(phydev, 0x9098, 0x01ff); ++ if (!(priv->chip_mode)) { /* rgmii config */ ++#if defined (YT8011_RGMII_DVDDIO_3V3) ++ ytphy_write_ext(phydev, 0x9000, 0x8000); ++ ytphy_write_ext(phydev, 0x0062, 0x0000); ++ ytphy_write_ext(phydev, 0x9000, 0x0000); ++ ytphy_write_ext(phydev, 0x9031, 0xb200); ++ ytphy_write_ext(phydev, 0x903b, 0x0040); ++ ytphy_write_ext(phydev, 0x903e, 0x3b3b); ++ ytphy_write_ext(phydev, 0x903c, 0xf); ++ ytphy_write_ext(phydev, 0x903d, 0x1000); ++ ytphy_write_ext(phydev, 0x9038, 0x0000); ++#elif defined (YT8011_RGMII_DVDDIO_2V5) ++ ytphy_write_ext(phydev, 0x9000, 0x8000); ++ ytphy_write_ext(phydev, 0x0062, 0x0000); ++ ytphy_write_ext(phydev, 0x9000, 0x0000); ++ ytphy_write_ext(phydev, 0x9031, 0xb200); ++ ytphy_write_ext(phydev, 0x9111, 0x5); ++ ytphy_write_ext(phydev, 0x9114, 0x3939); ++ ytphy_write_ext(phydev, 0x9112, 0xf); ++ ytphy_write_ext(phydev, 0x9110, 0x0); ++ ytphy_write_ext(phydev, 0x9113, 0x10); ++ ytphy_write_ext(phydev, 0x903d, 0x2); ++#elif defined (YT8011_RGMII_DVDDIO_1V8) ++ ytphy_write_ext(phydev, 0x9000, 0x8000); ++ ytphy_write_ext(phydev, 0x0062, 0x0000); ++ ytphy_write_ext(phydev, 0x9000, 0x0000); ++ ytphy_write_ext(phydev, 0x9031, 0xb200); ++ ytphy_write_ext(phydev, 0x9116, 0x6); ++ ytphy_write_ext(phydev, 0x9119, 0x3939); ++ ytphy_write_ext(phydev, 0x9117, 0xf); ++ ytphy_write_ext(phydev, 0x9115, 0x0); ++ ytphy_write_ext(phydev, 0x9118, 0x20); ++ ytphy_write_ext(phydev, 0x903d, 0x3); ++#endif ++ } ++ ++ ytphy_soft_reset(phydev); ++ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->addr); ++#else ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->mdio.addr); ++#endif ++ ++ return 0; ++} ++ ++static int ytxxxx_automotive_adjust_status(struct phy_device *phydev, int val) ++{ ++ int speed_mode; ++#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ int speed = -1; ++#else ++ int speed = SPEED_UNKNOWN; ++#endif ++ ++ speed_mode = (val & YTXXXX_SPEED_MODE) >> YTXXXX_SPEED_MODE_BIT; ++ switch (speed_mode) { ++ case 1: ++ speed = SPEED_100; ++ break; ++ case 2: ++ speed = SPEED_1000; ++ break; ++ default: ++#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ speed = -1; ++#else ++ speed = SPEED_UNKNOWN; ++#endif ++ break; ++ } ++ ++ phydev->speed = speed; ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static int yt8011_read_status(struct phy_device *phydev) + { + int ret; + int val; ++ int link; ++ int link_utp = 0; ++ ++ /* UTP */ ++ ret = ytphy_write_ext(phydev, 0x9000, 0x0); ++ if (ret < 0) ++ return ret; ++ ++ val = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val < 0) ++ return val; ++ ++ link = val & (BIT(YTXXXX_LINK_STATUS_BIT)); ++ if (link) { ++ link_utp = 1; ++ ytxxxx_automotive_adjust_status(phydev, val); ++ } else { ++ link_utp = 0; ++ } ++ ++ if (link_utp) { ++ if (phydev->link == 0) ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->addr, (unsigned int)val); ++#else ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->mdio.addr, ++ (unsigned int)val); ++#endif ++ phydev->link = 1; ++ } else { ++ if (phydev->link == 1) ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); ++#else ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); ++#endif ++ phydev->link = 0; ++ } ++ ++ if (link_utp) ++ ytphy_write_ext(phydev, 0x9000, 0x0); ++ ++ return 0; ++} ++ ++static int yt8512_led_init(struct phy_device *phydev) ++{ + int mask; ++ int ret; ++ int val; + + val = ytphy_read_ext(phydev, YT8512_EXTREG_LED0); + if (val < 0) +@@ -424,8 +786,8 @@ static int yt8512_led_init(struct phy_device *phydev) + val |= YT8512_LED0_ACT_BLK_IND; + + mask = YT8512_LED0_DIS_LED_AN_TRY | YT8512_LED0_BT_BLK_EN | +- YT8512_LED0_HT_BLK_EN | YT8512_LED0_COL_BLK_EN | +- YT8512_LED0_BT_ON_EN; ++ YT8512_LED0_HT_BLK_EN | YT8512_LED0_COL_BLK_EN | ++ YT8512_LED0_BT_ON_EN; + val &= ~mask; + + ret = ytphy_write_ext(phydev, YT8512_EXTREG_LED0, val); +@@ -446,11 +808,51 @@ static int yt8512_led_init(struct phy_device *phydev) + return ret; + } + ++static int yt8512_probe(struct phy_device *phydev) ++{ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ struct device *dev = &phydev->dev; ++#else ++ struct device *dev = &phydev->mdio.dev; ++#endif ++ struct yt8xxx_priv *priv; ++ int chip_config; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext(phydev, YT8512_EXTENDED_COMBO_CONTROL1); ++ ++ priv->chip_mode = (chip_config & (BIT(1) | BIT(0))); ++ ++ return 0; ++} ++ + static int yt8512_config_init(struct phy_device *phydev) + { ++ struct yt8xxx_priv *priv = phydev->priv; + int ret; + int val; + ++ val = ytphy_read_ext(phydev, YT8512_10BT_DEBUG_LPBKS); ++ if (val < 0) ++ return val; ++ ++ val &= ~BIT(10); ++ ret = ytphy_write_ext(phydev, YT8512_10BT_DEBUG_LPBKS, val); ++ if (ret < 0) ++ return ret; ++ ++ if (!(priv->chip_mode)) { /* MII mode */ ++ val &= ~BIT(15); ++ ret = ytphy_write_ext(phydev, YT8512_10BT_DEBUG_LPBKS, val); ++ if (ret < 0) ++ return ret; ++ } ++ + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) + ret = ytphy_config_init(phydev); + #else +@@ -472,25 +874,24 @@ static int yt8512_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + ++ ytphy_soft_reset(phydev); ++ + return ret; + } + + static int yt8512_read_status(struct phy_device *phydev) + { +- int ret; +- int val; + int speed, speed_mode, duplex; ++ int val; + +- ret = genphy_update_link(phydev); +- if (ret) +- return ret; ++ genphy_read_status(phydev); + + val = phy_read(phydev, REG_PHY_SPEC_STATUS); + if (val < 0) + return val; + +- duplex = (val & YT8512_DUPLEX) >> YT8512_DUPLEX_BIT; +- speed_mode = (val & YT8512_SPEED_MODE) >> YT8512_SPEED_MODE_BIT; ++ duplex = (val & YTXXXX_DUPLEX) >> YTXXXX_DUPLEX_BIT; ++ speed_mode = (val & YTXXXX_SPEED_MODE) >> YTXXXX_SPEED_MODE_BIT; + switch (speed_mode) { + case 0: + speed = SPEED_10; +@@ -515,35 +916,191 @@ static int yt8512_read_status(struct phy_device *phydev) + return 0; + } + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +-#else +-int yt8521_soft_reset(struct phy_device *phydev) ++static int yt8522_read_status(struct phy_device *phydev) + { +- int ret, val; ++ int speed, speed_mode, duplex; ++ int val; + +- if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_UTP) { +- ytphy_write_ext(phydev, 0xa000, 0); +- ytphy_soft_reset(phydev); +- } ++ genphy_read_status(phydev); + +- if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_FIBER) { +- ytphy_write_ext(phydev, 0xa000, 2); +- ytphy_soft_reset(phydev); ++ val = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val < 0) ++ return val; + +- ytphy_write_ext(phydev, 0xa000, 0); ++ if ((val & BIT(10)) >> YTXXXX_LINK_STATUS_BIT) { ++ duplex = (val & BIT(13)) >> YTXXXX_DUPLEX_BIT; ++ speed_mode = (val & (BIT(15) | BIT(14))) >> ++ YTXXXX_SPEED_MODE_BIT; ++ switch (speed_mode) { ++ case 0: ++ speed = SPEED_10; ++ break; ++ case 1: ++ speed = SPEED_100; ++ break; ++ case 2: ++ case 3: ++ default: ++#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ speed = -1; ++#else ++ speed = SPEED_UNKNOWN; ++#endif ++ break; ++ } ++ ++ phydev->link = 1; ++ phydev->speed = speed; ++ phydev->duplex = duplex; ++ ++ return 0; + } + +- if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_POLL) { +- val = ytphy_read_ext(phydev, 0xa001); +- ytphy_write_ext(phydev, 0xa001, (val & ~0x8000)); ++ phydev->link = 0; + +- ytphy_write_ext(phydev, 0xa000, 0); +- ret = ytphy_soft_reset(phydev); ++ return 0; ++} ++ ++static int yt8522_probe(struct phy_device *phydev) ++{ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ struct device *dev = &phydev->dev; ++#else ++ struct device *dev = &phydev->mdio.dev; ++#endif ++ struct yt8xxx_priv *priv; ++ int chip_config; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext(phydev, YT8522_EXTENDED_COMBO_CTRL_1); ++ ++ priv->chip_mode = (chip_config & (BIT(1) | BIT(0))); ++ ++ return 0; ++} ++ ++static int yt8522_config_init(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ int ret; ++ int val; ++ ++ val = ytphy_read_ext(phydev, YT8522_EXTENDED_COMBO_CTRL_1); ++ if (val < 0) ++ return val; ++ ++ /* RMII2 mode */ ++ if (0x2 == (priv->chip_mode)) { ++ val |= BIT(4); ++ ret = ytphy_write_ext(phydev, YT8522_EXTENDED_COMBO_CTRL_1, ++ val); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_TX_DELAY_CONTROL, 0x9f); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_EXTENDED_PAD_CONTROL, ++ 0x81d4); ++ if (ret < 0) ++ return ret; ++ } else if (0x3 == (priv->chip_mode)) { /* RMII1 mode */ ++ val |= BIT(4); ++ ret = ytphy_write_ext(phydev, YT8522_EXTENDED_COMBO_CTRL_1, ++ val); ++ if (ret < 0) ++ return ret; + } + ++#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) ++ ret = ytphy_config_init(phydev); ++#else ++ ret = genphy_config_init(phydev); ++#endif ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_TX_CLK_DELAY, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_ANAGLOG_IF_CTRL, 0xbf2a); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_DAC_CTRL, 0x297f); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_INTERPOLATOR_FILTER_1, 0x1FE); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, YT8522_INTERPOLATOR_FILTER_2, 0x1FE); ++ if (ret < 0) ++ return ret; ++ ++ /* disable auto sleep */ ++ val = ytphy_read_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1); ++ if (val < 0) ++ return val; ++ ++ val &= (~BIT(YT8512_EN_SLEEP_SW_BIT)); ++ ++ ret = ytphy_write_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1, val); ++ if (ret < 0) ++ return ret; ++ ++ ytphy_soft_reset(phydev); ++ + return 0; + } ++ ++static int yt8521_probe(struct phy_device *phydev) ++{ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ struct device *dev = &phydev->dev; ++#else ++ struct device *dev = &phydev->mdio.dev; + #endif ++ struct yt8xxx_priv *priv; ++ int chip_config; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext(phydev, 0xa001); ++ ++ priv->chip_mode = chip_config & 0x7; ++ switch (priv->chip_mode) { ++ case 1: /* fiber<>rgmii */ ++ case 4: ++ case 5: ++ priv->polling_mode = YT_PHY_MODE_FIBER; ++ break; ++ case 2: /* utp/fiber<>rgmii */ ++ case 6: ++ case 7: ++ priv->polling_mode = YT_PHY_MODE_POLL; ++ break; ++ case 3: /* utp<>sgmii */ ++ case 0: /* utp<>rgmii */ ++ default: ++ priv->polling_mode = YT_PHY_MODE_UTP; ++ break; ++ } ++ ++ return 0; ++} + + #if GMAC_CLOCK_INPUT_NEEDED + static int ytphy_mii_rd_ext(struct mii_bus *bus, int phy_id, u32 regnum) +@@ -560,10 +1117,8 @@ static int ytphy_mii_rd_ext(struct mii_bus *bus, int phy_id, u32 regnum) + return val; + } + +-static int ytphy_mii_wr_ext(struct mii_bus *bus +- int phy_id, +- u32 regnum, +- u16 val) ++static int ytphy_mii_wr_ext(struct mii_bus *bus, int phy_id, u32 regnum, ++ u16 val) + { + int ret; + +@@ -576,7 +1131,7 @@ static int ytphy_mii_wr_ext(struct mii_bus *bus + return ret; + } + +-int yt8511_config_dis_txdelay(struct mii_bus *bus, int phy_id) ++static int yt8511_config_dis_txdelay(struct mii_bus *bus, int phy_id) + { + int ret; + int val; +@@ -606,7 +1161,7 @@ int yt8511_config_dis_txdelay(struct mii_bus *bus, int phy_id) + return ret; + } + +-int yt8511_config_out_125m(struct mii_bus *bus, int phy_id) ++static int yt8511_config_out_125m(struct mii_bus *bus, int phy_id) + { + int ret; + int val; +@@ -640,7 +1195,6 @@ int yt8511_config_out_125m(struct mii_bus *bus, int phy_id) + /* for customer, please enable it based on demand. + * configure to master + */ +- + /* master/slave config reg*/ + val = bus->read(bus, phy_id, 0x9); + /* to be manual config and force to be master */ +@@ -665,11 +1219,15 @@ static int yt8511_config_init(struct phy_device *phydev) + #endif + + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", __func__, phydev->addr); ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->addr); + #else +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", __func__, phydev->mdio.addr); ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->mdio.addr); + #endif + ++ ytphy_soft_reset(phydev); ++ + return ret; + } + #endif /* GMAC_CLOCK_INPUT_NEEDED */ +@@ -688,7 +1246,7 @@ static int ytphy_switch_reg_space(struct phy_device *phydev, int space) + } + + static int ytphy_wol_feature_enable_cfg(struct phy_device *phydev, +- struct ytphy_wol_feature_cfg wol_cfg) ++ struct ytphy_wol_feature_cfg wol_cfg) + { + int ret = 0; + int val = 0; +@@ -700,27 +1258,27 @@ static int ytphy_wol_feature_enable_cfg(struct phy_device *phydev, + if (wol_cfg.enable) { + val |= YTPHY_WOL_FEATURE_ENABLE_CFG; + +- if (wol_cfg.type == YTPHY_WOL_FEATURE_LEVEL_TRIGGER) { +- val &= ~YTPHY_WOL_FEATURE_TYPE_CFG; +- val &= ~YTPHY_WOL_FEATURE_INTR_SEL_CFG; +- } else if (wol_cfg.type == YTPHY_WOL_FEATURE_PULSE_TRIGGER) { +- val |= YTPHY_WOL_FEATURE_TYPE_CFG; +- val |= YTPHY_WOL_FEATURE_INTR_SEL_CFG; +- +- if (wol_cfg.width == YTPHY_WOL_FEATURE_84MS_PULSE_WIDTH) { +- val &= ~YTPHY_WOL_FEATURE_WIDTH1_CFG; +- val &= ~YTPHY_WOL_FEATURE_WIDTH2_CFG; +- } else if (wol_cfg.width == YTPHY_WOL_FEATURE_168MS_PULSE_WIDTH) { +- val |= YTPHY_WOL_FEATURE_WIDTH1_CFG; +- val &= ~YTPHY_WOL_FEATURE_WIDTH2_CFG; +- } else if (wol_cfg.width == YTPHY_WOL_FEATURE_336MS_PULSE_WIDTH) { +- val &= ~YTPHY_WOL_FEATURE_WIDTH1_CFG; +- val |= YTPHY_WOL_FEATURE_WIDTH2_CFG; +- } else if (wol_cfg.width == YTPHY_WOL_FEATURE_672MS_PULSE_WIDTH) { +- val |= YTPHY_WOL_FEATURE_WIDTH1_CFG; +- val |= YTPHY_WOL_FEATURE_WIDTH2_CFG; ++ if (wol_cfg.type == YTPHY_WOL_FEATURE_LEVEL_TRIGGER) { ++ val &= ~YTPHY_WOL_FEATURE_TYPE_CFG; ++ val &= ~YTPHY_WOL_FEATURE_INTR_SEL_CFG; ++ } else if (wol_cfg.type == YTPHY_WOL_FEATURE_PULSE_TRIGGER) { ++ val |= YTPHY_WOL_FEATURE_TYPE_CFG; ++ val |= YTPHY_WOL_FEATURE_INTR_SEL_CFG; ++ ++ if (wol_cfg.width == YTPHY_WOL_FEATURE_84MS_PULSE_WIDTH) { ++ val &= ~YTPHY_WOL_FEATURE_WIDTH1_CFG; ++ val &= ~YTPHY_WOL_FEATURE_WIDTH2_CFG; ++ } else if (wol_cfg.width == YTPHY_WOL_FEATURE_168MS_PULSE_WIDTH) { ++ val |= YTPHY_WOL_FEATURE_WIDTH1_CFG; ++ val &= ~YTPHY_WOL_FEATURE_WIDTH2_CFG; ++ } else if (wol_cfg.width == YTPHY_WOL_FEATURE_336MS_PULSE_WIDTH) { ++ val &= ~YTPHY_WOL_FEATURE_WIDTH1_CFG; ++ val |= YTPHY_WOL_FEATURE_WIDTH2_CFG; ++ } else if (wol_cfg.width == YTPHY_WOL_FEATURE_672MS_PULSE_WIDTH) { ++ val |= YTPHY_WOL_FEATURE_WIDTH1_CFG; ++ val |= YTPHY_WOL_FEATURE_WIDTH2_CFG; ++ } + } +- } + } else { + val &= ~YTPHY_WOL_FEATURE_ENABLE_CFG; + val &= ~YTPHY_WOL_FEATURE_INTR_SEL_CFG; +@@ -734,7 +1292,7 @@ static int ytphy_wol_feature_enable_cfg(struct phy_device *phydev, + } + + static void ytphy_wol_feature_get(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) ++ struct ethtool_wolinfo *wol) + { + int val = 0; + +@@ -747,16 +1305,14 @@ static void ytphy_wol_feature_get(struct phy_device *phydev, + + if (val & YTPHY_WOL_FEATURE_ENABLE_CFG) + wol->wolopts |= WAKE_MAGIC; +- +- //return; + } + + static int ytphy_wol_feature_set(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) ++ struct ethtool_wolinfo *wol) + { +- int ret, curr_reg_space, val; +- struct ytphy_wol_feature_cfg wol_cfg; + struct net_device *p_attached_dev = phydev->attached_dev; ++ struct ytphy_wol_feature_cfg wol_cfg; ++ int ret, curr_reg_space, val; + + memset(&wol_cfg, 0, sizeof(struct ytphy_wol_feature_cfg)); + curr_reg_space = ytphy_read_ext(phydev, 0xa000); +@@ -785,19 +1341,23 @@ static int ytphy_wol_feature_set(struct phy_device *phydev, + return ret; + + /* Store the device address for the magic packet */ +- ret = ytphy_write_ext(phydev, YTPHY_WOL_FEATURE_MACADDR2_4_MAGIC_PACKET, +- ((p_attached_dev->dev_addr[0] << 8) | +- p_attached_dev->dev_addr[1])); ++ ret = ytphy_write_ext(phydev, ++ YTPHY_WOL_FEATURE_MACADDR2_4_MAGIC_PACKET, ++ ((p_attached_dev->dev_addr[0] << 8) | ++ p_attached_dev->dev_addr[1])); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, YTPHY_WOL_FEATURE_MACADDR1_4_MAGIC_PACKET, +- ((p_attached_dev->dev_addr[2] << 8) | +- p_attached_dev->dev_addr[3])); ++ ret = ytphy_write_ext(phydev, ++ YTPHY_WOL_FEATURE_MACADDR1_4_MAGIC_PACKET, ++ ((p_attached_dev->dev_addr[2] << 8) | ++ p_attached_dev->dev_addr[3])); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, YTPHY_WOL_FEATURE_MACADDR0_4_MAGIC_PACKET, +- ((p_attached_dev->dev_addr[4] << 8) | +- p_attached_dev->dev_addr[5])); ++ ++ ret = ytphy_write_ext(phydev, ++ YTPHY_WOL_FEATURE_MACADDR0_4_MAGIC_PACKET, ++ ((p_attached_dev->dev_addr[4] << 8) | ++ p_attached_dev->dev_addr[5])); + if (ret < 0) + return ret; + } else { +@@ -818,32 +1378,12 @@ static int ytphy_wol_feature_set(struct phy_device *phydev, + } + #endif /*(YTPHY_WOL_FEATURE_ENABLE)*/ + +-static int yt8521_hw_strap_polling(struct phy_device *phydev) +-{ +- int val = 0; +- +- val = ytphy_read_ext(phydev, 0xa001) & 0x7; +- switch (val) { +- case 1: +- case 4: +- case 5: +- return YT8521_PHY_MODE_FIBER; +- case 2: +- case 6: +- case 7: +- return YT8521_PHY_MODE_POLL; +- case 3: +- case 0: +- default: +- return YT8521_PHY_MODE_UTP; +- } +-} +- +- + static int yt8521_config_init(struct phy_device *phydev) + { + int ret; +- int val, hw_strap_mode; ++ int val, chip_config; ++ ++ struct yt8xxx_priv *priv = phydev->priv; + + #if (YTPHY_WOL_FEATURE_ENABLE) + struct ethtool_wolinfo wol; +@@ -853,16 +1393,18 @@ static int yt8521_config_init(struct phy_device *phydev) + wol.wolopts |= WAKE_MAGIC; + ytphy_wol_feature_set(phydev, &wol); + #endif ++ + if (phydev->force_mode) { +- hw_strap_mode = ytphy_read_ext(phydev, 0xa001) & 0x7; +- hw_strap_mode = hw_strap_mode & 0x7ff8; +- hw_strap_mode = hw_strap_mode |0x140; +- ytphy_write_ext(phydev, 0xa001, hw_strap_mode); ++ chip_config = ytphy_read_ext(phydev, 0xa001) & 0x7; ++ chip_config = chip_config & 0x7ff8; ++ chip_config = chip_config | 0x140; ++ ytphy_write_ext(phydev, 0xa001, chip_config); ++ ++ priv->chip_mode = chip_config & 0x7; ++ priv->polling_mode = YT_PHY_MODE_UTP; + } + + phydev->irq = PHY_POLL; +- /* NOTE: this function should not be called more than one for each chip. */ +- hw_strap_mode = ytphy_read_ext(phydev, 0xa001) & 0x7; + + ytphy_write_ext(phydev, 0xa000, 0); + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) +@@ -893,20 +1435,27 @@ static int yt8521_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + ++ ytxxxx_soft_reset(phydev); ++ + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, strap mode = %d, polling mode = %d\n", +- __func__, phydev->addr, hw_strap_mode, yt8521_hw_strap_polling(phydev)); ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode = %d, polling mode = %d\n", ++ __func__, phydev->addr, ++ priv->chip_mode, priv->polling_mode); + #else +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, strap mode = %d, polling mode = %d\n", +- __func__, phydev->mdio.addr, hw_strap_mode, yt8521_hw_strap_polling(phydev)); ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode = %d, polling mode = %d\n", ++ __func__, phydev->mdio.addr, ++ priv->chip_mode, priv->polling_mode); + #endif ++ + return ret; + } + + /* for fiber mode, there is no 10M speed mode and + * this function is for this purpose. + */ +-static int yt8521_adjust_status(struct phy_device *phydev, int val, int is_utp) ++static int ytxxxx_adjust_status(struct phy_device *phydev, int val, int is_utp) + { + int speed_mode, duplex; + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +@@ -916,10 +1465,10 @@ static int yt8521_adjust_status(struct phy_device *phydev, int val, int is_utp) + #endif + + if (is_utp) +- duplex = (val & YT8512_DUPLEX) >> YT8521_DUPLEX_BIT; ++ duplex = (val & YTXXXX_DUPLEX) >> YTXXXX_DUPLEX_BIT; + else + duplex = 1; +- speed_mode = (val & YT8521_SPEED_MODE) >> YT8521_SPEED_MODE_BIT; ++ speed_mode = (val & YTXXXX_SPEED_MODE) >> YTXXXX_SPEED_MODE_BIT; + switch (speed_mode) { + case 0: + if (is_utp) +@@ -939,7 +1488,7 @@ static int yt8521_adjust_status(struct phy_device *phydev, int val, int is_utp) + #else + speed = SPEED_UNKNOWN; + #endif +- break; ++ break; + } + + phydev->speed = speed; +@@ -952,125 +1501,181 @@ static int yt8521_adjust_status(struct phy_device *phydev, int val, int is_utp) + * autonegotiation, and this function handles this case and return + * 1 per linux kernel's polling. + */ +-int yt8521_aneg_done(struct phy_device *phydev) ++static int yt8521_aneg_done(struct phy_device *phydev) + { + int link_fiber = 0, link_utp = 0; + + /* reading Fiber */ + ytphy_write_ext(phydev, 0xa000, 2); +- link_fiber = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); ++ link_fiber = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & ++ (BIT(YTXXXX_LINK_STATUS_BIT))); + + /* reading UTP */ + ytphy_write_ext(phydev, 0xa000, 0); + if (!link_fiber) +- link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); ++ link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & ++ (BIT(YTXXXX_LINK_STATUS_BIT))); + + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_fiber: %d, link_utp: %d\n", +- __func__, phydev->addr, link_fiber, link_utp); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link_fiber: %d, link_utp: %d\n", ++ __func__, phydev->addr, link_fiber, link_utp); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_fiber: %d, link_utp: %d\n", +- __func__, phydev->mdio.addr, link_fiber, link_utp); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link_fiber: %d, link_utp: %d\n", ++ __func__, phydev->mdio.addr, link_fiber, link_utp); + #endif ++ + return !!(link_fiber | link_utp); + } + + static int yt8521_read_status(struct phy_device *phydev) + { +- int ret; +- int val; ++ struct yt8xxx_priv *priv = phydev->priv; ++ int link_utp = 0, link_fiber = 0; + int yt8521_fiber_latch_val; + int yt8521_fiber_curr_val; ++ int val_utp, val_fiber; + int link; +- int link_utp = 0, link_fiber = 0; ++ int ret; ++ int lpa; + +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ if(priv->polling_mode != YT_PHY_MODE_FIBER) { + /* reading UTP */ + ret = ytphy_write_ext(phydev, 0xa000, 0); + if (ret < 0) + return ret; + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; ++ val_utp = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val_utp < 0) ++ return val_utp; + +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); ++ link = val_utp & (BIT(YTXXXX_LINK_STATUS_BIT)); + if (link) { + link_utp = 1; +- yt8521_adjust_status(phydev, val, 1); ++ ytxxxx_adjust_status(phydev, val_utp, 1); + } else { + link_utp = 0; + } +- } //(YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) + +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) { ++ if (link_utp) { ++ lpa = phy_read(phydev, MII_LPA); ++ if (ret < 0) ++ return ret; ++ ++ phydev->pause = !!(lpa & BIT(10)); ++ phydev->asym_pause = !!(lpa & BIT(11)); ++ } ++ } ++ ++ if (priv->polling_mode != YT_PHY_MODE_UTP) { + /* reading Fiber */ + ret = ytphy_write_ext(phydev, 0xa000, 2); +- if (ret < 0) ++ if (ret < 0) { ++ ytphy_write_ext(phydev, 0xa000, 0); + return ret; ++ } + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; +- +- //note: below debug information is used to check multiple PHy ports. ++ val_fiber = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val_fiber < 0) { ++ ytphy_write_ext(phydev, 0xa000, 0); ++ return val_fiber; ++ } + +- /* for fiber, from 1000m to 100m, there is not link down from 0x11, +- * and check reg 1 to identify such case this is important for Linux +- * kernel for that, missing linkdown event will cause problem. ++ /* for fiber, from 1000m to 100m, there is not link down ++ * from 0x11, and check reg 1 to identify such case ++ * this is important for Linux kernel for that, missing linkdown ++ * event will cause problem. + */ + yt8521_fiber_latch_val = phy_read(phydev, MII_BMSR); + yt8521_fiber_curr_val = phy_read(phydev, MII_BMSR); +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); ++ link = val_fiber & (BIT(YTXXXX_LINK_STATUS_BIT)); + if (link && yt8521_fiber_latch_val != yt8521_fiber_curr_val) { + link = 0; +-#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->addr, yt8521_fiber_latch_val, yt8521_fiber_curr_val); ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", ++ __func__, phydev->addr, ++ yt8521_fiber_latch_val, ++ yt8521_fiber_curr_val); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->mdio.addr, yt8521_fiber_latch_val, yt8521_fiber_curr_val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", ++ __func__, phydev->mdio.addr, ++ yt8521_fiber_latch_val, ++ yt8521_fiber_curr_val); + #endif + } + + if (link) { + link_fiber = 1; +- yt8521_adjust_status(phydev, val, 0); ++ ytxxxx_adjust_status(phydev, val_fiber, 0); + } else { + link_fiber = 0; + } +- } //(YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) ++ ++ if (link_fiber) { ++ lpa = phy_read(phydev, MII_LPA); ++ if (ret < 0) { ++ ytphy_write_ext(phydev, 0xa000, 0); ++ return ret; ++ } ++ ++ phydev->pause = !!(lpa & BIT(7)); ++ phydev->asym_pause = !!(lpa & BIT(8)); ++ } ++ } + + if (link_utp || link_fiber) { + if (phydev->link == 0) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", +- __func__, phydev->addr, (link_utp && link_fiber) ? "UNKNOWN MEDIA" : (link_utp ? "UTP" : "Fiber"), (unsigned int)val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->addr, ++ (link_utp && link_fiber) ? ++ "UNKNOWN MEDIA" : ++ (link_utp ? "UTP" : "Fiber"), ++ link_utp ? (unsigned int)val_utp : ++ (unsigned int)val_fiber); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", +- __func__, phydev->mdio.addr, (link_utp && link_fiber) ? "UNKNOWN MEDIA" : (link_utp ? "UTP" : "Fiber"), (unsigned int)val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->mdio.addr, ++ (link_utp && link_fiber) ? ++ "UNKNOWN MEDIA" : ++ (link_utp ? "UTP" : "Fiber"), ++ link_utp ? (unsigned int)val_utp : ++ (unsigned int)val_fiber); + #endif + phydev->link = 1; + } else { + if (phydev->link == 1) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->mdio.addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); + #endif + phydev->link = 0; + } + +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { //utp or combo ++ if (priv->polling_mode != YT_PHY_MODE_FIBER) { + if (link_fiber) + ytphy_write_ext(phydev, 0xa000, 2); +- if (link_utp) ++ else + ytphy_write_ext(phydev, 0xa000, 0); + } ++ + return 0; + } + +-int yt8521_suspend(struct phy_device *phydev) ++static int yt8521_suspend(struct phy_device *phydev) + { + #if !(SYS_WAKEUP_BASED_ON_ETH_PKT) + int value; +@@ -1080,14 +1685,19 @@ int yt8521_suspend(struct phy_device *phydev) + #else + /* no need lock in 4.19 */ + #endif ++ struct yt8xxx_priv *priv = phydev->priv; + +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ if (priv->polling_mode != YT_PHY_MODE_FIBER) { ++ ytphy_write_ext(phydev, 0xa000, 0); ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ } + +- ytphy_write_ext(phydev, 0xa000, 2); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ if (priv->polling_mode != YT_PHY_MODE_UTP) { ++ ytphy_write_ext(phydev, 0xa000, 2); ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ } + + ytphy_write_ext(phydev, 0xa000, 0); + +@@ -1096,12 +1706,12 @@ int yt8521_suspend(struct phy_device *phydev) + #else + /* no need lock/unlock in 4.19 */ + #endif +-#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; + } + +-int yt8521_resume(struct phy_device *phydev) ++static int yt8521_resume(struct phy_device *phydev) + { + int value, ret; + +@@ -1122,46 +1732,91 @@ int yt8521_resume(struct phy_device *phydev) + #else + /* no need lock/unlock in 4.19 */ + #endif ++ struct yt8xxx_priv *priv = phydev->priv; + +- /* power down both sds & phy in suspend, power up both too */ +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ if (priv->polling_mode != YT_PHY_MODE_FIBER) { ++ ytphy_write_ext(phydev, 0xa000, 0); ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ } + +- ytphy_write_ext(phydev, 0xa000, 2); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ if (priv->polling_mode != YT_PHY_MODE_UTP) { ++ ytphy_write_ext(phydev, 0xa000, 2); ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); + +- ytphy_write_ext(phydev, 0xa000, 0); ++ ytphy_write_ext(phydev, 0xa000, 0); ++ } + + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) + mutex_unlock(&phydev->lock); + #else + /* no need lock/unlock in 4.19 */ + #endif +-#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; + } + + static int yt8531S_config_init(struct phy_device *phydev) + { +- int ret = 0; ++ int ret = 0, val = 0; + + #if (YTPHY8531A_XTAL_INIT) + ret = yt8531a_xtal_init(phydev); + if (ret < 0) + return ret; + #endif ++ ret = ytphy_write_ext(phydev, 0xa023, 0x4031); ++ if (ret < 0) ++ return ret; ++ ++ ytphy_write_ext(phydev, 0xa000, 0x0); ++ val = ytphy_read_ext(phydev, 0xf); ++ ++ if(0x31 != val && 0x32 != val) { ++ ret = ytphy_write_ext(phydev, 0xa071, 0x9007); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0x52, 0x231d); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0x51, 0x04a9); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0x57, 0x274c); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa006, 0x10d); ++ if (ret < 0) ++ return ret; ++ ++ if(0x500 == val) { ++ val = ytphy_read_ext(phydev, 0xa001); ++ if((0x30 == (val & 0x30)) || (0x20 == (val & 0x30))) { ++ ret = ytphy_write_ext(phydev, 0xa010, 0xabff); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ } + + ret = yt8521_config_init(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ytphy_write_ext(phydev, 0xa000, 0x0); + + return ret; + } + + static int yt8531_config_init(struct phy_device *phydev) + { +- int ret = 0; ++ int ret = 0, val = 0; + + #if (YTPHY8531A_XTAL_INIT) + ret = yt8531a_xtal_init(phydev); +@@ -1177,69 +1832,69 @@ static int yt8531_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- return 0; +-} ++ val = ytphy_read_ext(phydev, 0xf); ++ if(0x31 != val && 0x32 != val) { ++ ret = ytphy_write_ext(phydev, 0x52, 0x231d); ++ if (ret < 0) ++ return ret; + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +-#else +-int yt8618_soft_reset(struct phy_device *phydev) +-{ +- int ret; ++ ret = ytphy_write_ext(phydev, 0x51, 0x04a9); ++ if (ret < 0) ++ return ret; + +- ytphy_write_ext(phydev, 0xa000, 0); +- ret = ytphy_soft_reset(phydev); +- if (ret < 0) +- return ret; ++ ret = ytphy_write_ext(phydev, 0x57, 0x274c); ++ if (ret < 0) ++ return ret; ++ ++ if(0x500 == val) { ++ val = ytphy_read_ext(phydev, 0xa001); ++ if((0x30 == (val & 0x30)) || (0x20 == (val & 0x30))) { ++ ret = ytphy_write_ext(phydev, 0xa010, 0xabff); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ } ++ ++ ytphy_soft_reset(phydev); + + return 0; + } + +-int yt8614_soft_reset(struct phy_device *phydev) ++#if (KERNEL_VERSION(5, 0, 21) < LINUX_VERSION_CODE) ++static void ytphy_link_change_notify(struct phy_device *phydev) + { +- int ret; ++ int adv; + +- /* qsgmii */ +- ytphy_write_ext(phydev, 0xa000, 2); +- ret = ytphy_soft_reset(phydev); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); +- return ret; +- } +- +- /* sgmii */ +- ytphy_write_ext(phydev, 0xa000, 3); +- ret = ytphy_soft_reset(phydev); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); +- return ret; +- } ++ adv = phy_read(phydev, MII_ADVERTISE); ++ if (adv < 0) ++ return; + +- /* utp */ +- ytphy_write_ext(phydev, 0xa000, 0); +- ret = ytphy_soft_reset(phydev); +- if (ret < 0) +- return ret; ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, ++ phydev->advertising, (adv & ADVERTISE_10HALF)); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, ++ phydev->advertising, (adv & ADVERTISE_10FULL)); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, ++ phydev->advertising, (adv & ADVERTISE_100HALF)); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, ++ phydev->advertising, (adv & ADVERTISE_100FULL)); ++ ++ adv = phy_read(phydev, MII_CTRL1000); ++ if (adv < 0) ++ return; + +- return 0; ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->advertising, (adv & ADVERTISE_1000HALF)); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->advertising, (adv & ADVERTISE_1000FULL)); + } + #endif + +-static int yt8618_config_init(struct phy_device *phydev) ++#ifdef YTPHY_YT8543_ENABLE ++static int yt8543_config_init(struct phy_device *phydev) + { +- int ret; +- int val; +- unsigned int retries = 12; +-#if (YTPHY_861X_ABC_VER) +- int port = 0; +-#endif +- +- phydev->irq = PHY_POLL; +- +-#if (YTPHY_861X_ABC_VER) +- port = yt8614_get_port_from_phydev(phydev); +-#endif ++ int ret = 0, val = 0; + +- ytphy_write_ext(phydev, 0xa000, 0); + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) + ret = ytphy_config_init(phydev); + #else +@@ -1248,123 +1903,371 @@ static int yt8618_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- /* for utp to optimize signal */ +- ret = ytphy_write_ext(phydev, 0x41, 0x33); ++ ret = ytphy_write_ext(phydev, 0x403c, 0x286); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x42, 0x66); ++ ++ ret = ytphy_write_ext(phydev, 0xdc, 0x855c); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x43, 0xaa); ++ ++ ret = ytphy_write_ext(phydev, 0xdd, 0x6040); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x44, 0xd0d); ++ ++ ret = ytphy_write_ext(phydev, 0x40e, 0xf00); + if (ret < 0) + return ret; + +-#if (YTPHY_861X_ABC_VER) +- if ((port == 2) || (port == 5)) { +- ret = ytphy_write_ext(phydev, 0x57, 0x2929); +- if (ret < 0) +- return ret; +- } +-#endif ++ ret = ytphy_write_ext(phydev, 0x40f, 0xf00); ++ if (ret < 0) ++ return ret; + +- val = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, val | BMCR_RESET); +- do { +- msleep(50); +- ret = phy_read(phydev, MII_BMCR); +- if (ret < 0) +- return ret; +- } while ((ret & BMCR_RESET) && --retries); +- if (ret & BMCR_RESET) +- return -ETIMEDOUT; ++ ret = ytphy_write_ext(phydev, 0x411, 0x5030); ++ if (ret < 0) ++ return ret; + +- /* for QSGMII optimization */ +- ytphy_write_ext(phydev, 0xa000, 0x02); ++ ret = ytphy_write_ext(phydev, 0x1f, 0x110a); ++ if (ret < 0) ++ return ret; + +- ret = ytphy_write_ext(phydev, 0x3, 0x4F80); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++ ret = ytphy_write_ext(phydev, 0x20, 0xc06); ++ if (ret < 0) + return ret; +- } +- ret = ytphy_write_ext(phydev, 0xe, 0x4F80); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++ ++ ret = ytphy_write_ext(phydev, 0x40d, 0x1f); ++ if (ret < 0) + return ret; +- } + +- ytphy_write_ext(phydev, 0xa000, 0); ++ val = ytphy_read_ext(phydev, 0xa088); ++ if (val < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa088, ++ ((val & 0xfff0) | BIT(4)) | ++ (((ytphy_read_ext(phydev, 0xa015) & 0x3c)) >> 2)); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa183, 0x1918); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa184, 0x1818); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa186, 0x2018); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa189, 0x3894); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa187, 0x3838); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa18b, 0x1918); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa18c, 0x1818); ++ if (ret < 0) ++ return ret; ++ ++ ytphy_soft_reset(phydev); + ++ return 0; ++} ++ ++static int yt8543_read_status(struct phy_device *phydev) ++{ ++ int link_utp = 0; ++ int link; ++ int val; ++ ++ genphy_read_status(phydev); ++ ++ val = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val < 0) ++ return val; ++ ++ link = val & (BIT(YTXXXX_LINK_STATUS_BIT)); ++ if (link) { ++ link_utp = 1; ++ ytxxxx_adjust_status(phydev, val, 1); ++ } else { ++ link_utp = 0; ++ } ++ ++ if (link_utp) { ++ if (phydev->link == 0) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", __func__, phydev->addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->addr, (unsigned int)val); + #else +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", __func__, phydev->mdio.addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->mdio.addr, ++ (unsigned int)val); + #endif +- return ret; ++ phydev->link = 1; ++ } else { ++ if (phydev->link == 1) ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); ++#else ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); ++#endif ++ ++ phydev->link = 0; ++ } ++ ++ return 0; + } ++#endif + +-static int yt8614_hw_strap_polling(struct phy_device *phydev) ++static int yt8614_probe(struct phy_device *phydev) + { +- int val = 0; ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ struct device *dev = &phydev->dev; ++#else ++ struct device *dev = &phydev->mdio.dev; ++#endif ++ struct yt8xxx_priv *priv; ++ int chip_config; + +- val = ytphy_read_ext(phydev, 0xa007) & 0xf; +- switch (val) { +- case 8: //4'b1000, Fiber x4 + Copper x4 +- case 12: //4'b1100, QSGMII x1 + Combo x4 mode; +- case 13: //4'b1101, QSGMII x1 + Combo x4 mode; +- return (YT_PHY_MODE_FIBER | YT_PHY_MODE_UTP); +- case 14: //4'b1110, QSGMII x1 + SGMII(MAC) x4 mode; +- case 11: //4'b1011, QSGMII x1 + Fiber x4 mode; +- return YT_PHY_MODE_FIBER; +- case 9: //4'b1001, Reserved. +- case 10: //4'b1010, QSGMII x1 + Copper x4 mode +- case 15: //4'b1111, SGMII(PHY) x4 + Copper x4 mode ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext(phydev, 0xa007); ++ ++ priv->chip_mode = chip_config & 0xf; ++ switch (priv->chip_mode) { ++ case 8: /* 4'b1000, Fiber x4 + Copper x4 */ ++ case 12: /* 4'b1100, QSGMII x1 + Combo x4 mode; */ ++ case 13: /* 4'b1101, QSGMII x1 + Combo x4 mode; */ ++ priv->polling_mode = (YT_PHY_MODE_FIBER | YT_PHY_MODE_UTP); ++ break; ++ case 14: /* 4'b1110, QSGMII x1 + SGMII(MAC) x4 mode; */ ++ case 11: /* 4'b1011, QSGMII x1 + Fiber x4 mode; */ ++ priv->polling_mode = YT_PHY_MODE_FIBER; ++ break; ++ case 9: /* 4'b1001, Reserved. */ ++ case 10: /* 4'b1010, QSGMII x1 + Copper x4 mode */ ++ case 15: /* 4'b1111, SGMII(PHY) x4 + Copper x4 mode */ + default: +- return YT_PHY_MODE_UTP; ++ priv->polling_mode = YT_PHY_MODE_UTP; ++ break; + } ++ ++ return 0; + } + +-#if (YTPHY_861X_ABC_VER) +-static int yt8614_get_port_from_phydev(struct phy_device *phydev) ++static int yt8614Q_probe(struct phy_device *phydev) + { +- int tmp = ytphy_read_ext(phydev, 0xa0ff); +- int phy_addr = 0; +- + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- phy_addr = (unsigned int)phydev->addr; ++ struct device *dev = &phydev->dev; + #else +- phy_addr = (unsigned int)phydev->mdio.addr; ++ struct device *dev = &phydev->mdio.dev; + #endif ++ struct yt8xxx_priv *priv; ++ int chip_config; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + +- if ((phy_addr - tmp) < 0) { +- ytphy_write_ext(phydev, 0xa0ff, phy_addr); +- tmp = phy_addr; ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext(phydev, 0xa007); ++ ++ priv->chip_mode = chip_config & 0xf; ++ switch (priv->chip_mode) { ++ case 0x1: /* 4'b0001, QSGMII to 1000BASE-X or 100BASE-FX x 4 */ ++ priv->polling_mode = YT_PHY_MODE_FIBER; ++ break; ++ default: ++ break; + } + +- return (phy_addr - tmp); ++ return 0; + } +-#endif + +-static int yt8614_config_init(struct phy_device *phydev) ++static int yt8614Q_config_aneg(struct phy_device *phydev) + { +- int ret = 0; +- int val, hw_strap_mode; +- unsigned int retries = 12; +-#if (YTPHY_861X_ABC_VER) +- int port = 0; +-#endif +- phydev->irq = PHY_POLL; ++ return 0; ++} ++ ++static int yt8618_soft_reset(struct phy_device *phydev) ++{ ++ int ret; + +- /* NOTE: this function should not be called more than one for each chip. */ +- hw_strap_mode = ytphy_read_ext(phydev, 0xa007) & 0xf; ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; + +-#if (YTPHY_861X_ABC_VER) +- port = yt8614_get_port_from_phydev(phydev); +-#endif ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) ++ return ret; + +- ytphy_write_ext(phydev, 0xa000, 0); ++ return 0; ++} ++ ++static int __ytphy_write_page(struct phy_device *phydev, int page) ++{ ++ return __ytphy_write_ext(phydev, YTPHY_REG_SMI_MUX, page); ++} ++ ++static int __ytphy_read_page(struct phy_device *phydev) ++{ ++ return __ytphy_read_ext(phydev, YTPHY_REG_SMI_MUX); ++} ++ ++static int ytphy_save_page(struct phy_device *phydev) ++{ ++ /* mutex_lock(&phydev->mdio.bus->mdio_lock); */ ++ phy_lock_mdio_bus(phydev); ++ return __ytphy_read_page(phydev); ++} ++ ++static int ytphy_select_page(struct phy_device *phydev, int page) ++{ ++ int ret, oldpage; ++ ++ oldpage = ret = ytphy_save_page(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (oldpage != page) { ++ ret = __ytphy_write_page(phydev, page); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return oldpage; ++} ++ ++static int ytphy_restore_page(struct phy_device *phydev, int oldpage, int ret) ++{ ++ int r; ++ ++ if (oldpage >= 0) { ++ r = __ytphy_write_page(phydev, oldpage); ++ ++ /* Propagate the operation return code if the page write ++ * was successful. ++ */ ++ if (ret >= 0 && r < 0) ++ ret = r; ++ } else { ++ /* Propagate the phy page selection error code */ ++ ret = oldpage; ++ } ++ ++ /* mutex_unlock(&phydev->mdio.bus->mdio_lock); */ ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++static int yt861x_soft_reset_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage >= 0) ++ ret = __ytphy_soft_reset(phydev); ++ ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8614_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_SGMII); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int yt8614Q_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt861x_soft_reset_paged(phydev, YT8614_REG_SPACE_SGMII); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int yt8618_config_init_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ if (reg_space == YT8614_REG_SPACE_UTP) { ++ ret = __ytphy_write_ext(phydev, 0x41, 0x33); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x42, 0x66); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x43, 0xaa); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x44, 0xd0d); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x57, 0x234f); ++ if (ret < 0) ++ goto err_restore_page; ++ } else if (reg_space == YT8614_REG_SPACE_QSGMII) { ++ ret = __ytphy_write_ext(phydev, 0x3, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0xe, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ } ++ ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8618_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ phydev->irq = PHY_POLL; + + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) + ret = ytphy_config_init(phydev); +@@ -1374,554 +2277,804 @@ static int yt8614_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- /* for utp to optimize signal */ +- ret = ytphy_write_ext(phydev, 0x41, 0x33); ++ ret = ytphy_write_ext(phydev, 0xa040, 0xbb00); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x42, 0x66); ++ ret = ytphy_write_ext(phydev, 0xa041, 0xbb00); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x43, 0xaa); ++ ret = ytphy_write_ext(phydev, 0xa042, 0xbb00); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x44, 0xd0d); ++ ret = ytphy_write_ext(phydev, 0xa043, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa044, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa045, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa046, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa047, 0xbb00); + if (ret < 0) + return ret; + +-#if (YTPHY_861X_ABC_VER) +- if (port == 2) { +- ret = ytphy_write_ext(phydev, 0x57, 0x2929); +- if (ret < 0) +- return ret; +- } ++ ret = yt8618_config_init_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8618_config_init_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++ ++ yt8618_soft_reset(phydev); ++ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d\n", __func__, phydev->addr); ++#else ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d\n", __func__, phydev->mdio.addr); + #endif + +- /* soft reset to take config effect */ +- val = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, val | BMCR_RESET); +- do { +- msleep(50); +- ret = phy_read(phydev, MII_BMCR); ++ return ret; ++} ++ ++static int yt8614_config_init_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ if (reg_space == YT8614_REG_SPACE_UTP) { ++ ret = __ytphy_write_ext(phydev, 0x41, 0x33); + if (ret < 0) +- return ret; +- } while ((ret & BMCR_RESET) && --retries); +- if (ret & BMCR_RESET) +- return -ETIMEDOUT; ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x42, 0x66); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x43, 0xaa); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x44, 0xd0d); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x57, 0x2929); ++ if (ret < 0) ++ goto err_restore_page; ++ } else if (reg_space == YT8614_REG_SPACE_QSGMII) { ++ ret = __ytphy_write_ext(phydev, 0x3, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0xe, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ } else if (reg_space == YT8614_REG_SPACE_SGMII) { ++ ret = __ytphy_write_ext(phydev, 0x3, 0x2420); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0xe, 0x24a0); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0x1be, 0xb01f); ++ if (ret < 0) ++ goto err_restore_page; ++ } + +- /* for QSGMII optimization */ +- ytphy_write_ext(phydev, 0xa000, 0x02); +- ret = ytphy_write_ext(phydev, 0x3, 0x4F80); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8614_config_init(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ int ret = 0; ++ ++ phydev->irq = PHY_POLL; ++ ++ ret = ytphy_write_ext(phydev, 0xa040, 0xbb00); ++ if (ret < 0) + return ret; +- } +- ret = ytphy_write_ext(phydev, 0xe, 0x4F80); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++ ret = ytphy_write_ext(phydev, 0xa041, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa042, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa043, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa044, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa045, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa046, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa047, 0xbb00); ++ if (ret < 0) ++ return ret; ++ ret = ytphy_write_ext(phydev, 0xa08e, 0xf10); ++ if (ret < 0) + return ret; +- } + +- /* for SGMII optimization */ +- ytphy_write_ext(phydev, 0xa000, 0x03); +- ret = ytphy_write_ext(phydev, 0x3, 0x2420); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++ ret = yt8614_config_init_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) + return ret; +- } +- ret = ytphy_write_ext(phydev, 0xe, 0x24a0); +- if (ret < 0) { +- ytphy_write_ext(phydev, 0xa000, 0); ++ ++ ret = yt8614_config_init_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) + return ret; ++ ++ ret = yt8614_config_init_paged(phydev, YT8614_REG_SPACE_SGMII); ++ if (ret < 0) ++ return ret; ++ ++ yt8614_soft_reset(phydev); ++ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode: %d, polling mode = %d\n", ++ __func__, ++ phydev->addr, priv->chip_mode, priv->polling_mode); ++#else ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode: %d, polling mode = %d\n", ++ __func__, ++ phydev->mdio.addr, priv->chip_mode, priv->polling_mode); ++#endif ++ ++ return ret; ++} ++ ++static int yt8614Q_config_init_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ if (reg_space == YT8614_REG_SPACE_QSGMII) { ++ ret = __ytphy_write_ext(phydev, 0x3, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0xe, 0x4F80); ++ if (ret < 0) ++ goto err_restore_page; ++ } else if (reg_space == YT8614_REG_SPACE_SGMII) { ++ ret = __ytphy_write_ext(phydev, 0x3, 0x2420); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __ytphy_write_ext(phydev, 0xe, 0x24a0); ++ if (ret < 0) ++ goto err_restore_page; + } + +- /* back up to utp*/ +- ytphy_write_ext(phydev, 0xa000, 0); ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8614Q_config_init(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ int ret = 0; ++ ++ phydev->irq = PHY_POLL; ++ ++ ret = ytphy_write_ext(phydev, 0xa056, 0x7); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8614Q_config_init_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8614Q_config_init_paged(phydev, YT8614_REG_SPACE_SGMII); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8614Q_soft_reset(phydev); ++ if (ret < 0) ++ return ret; + + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, chip mode: %d\n", __func__, phydev->addr, hw_strap_mode); ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode: %d, polling mode = %d\n", ++ __func__, ++ phydev->addr, priv->chip_mode, priv->polling_mode); + #else +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, chip mode: %d\n", __func__, phydev->mdio.addr, hw_strap_mode); ++ netdev_info(phydev->attached_dev, ++ "%s done, phy addr: %d, chip mode: %d, polling mode = %d\n", ++ __func__, ++ phydev->mdio.addr, priv->chip_mode, priv->polling_mode); + #endif +- return ret; ++ return 0; + } + +-int yt8618_aneg_done(struct phy_device *phydev) ++static int yt8618_aneg_done(struct phy_device *phydev) + { +-#if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- return genphy_aneg_done(phydev); +-#else +- return 1; +-#endif ++ return !!(yt861x_aneg_done_paged(phydev, YT8614_REG_SPACE_UTP)); ++} ++ ++static int yt861x_aneg_done_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage >= 0) ++ ret = !!(__phy_read(phydev, REG_PHY_SPEC_STATUS) & ++ (BIT(YTXXXX_LINK_STATUS_BIT))); ++ ++ return ytphy_restore_page(phydev, oldpage, ret); + } + +-int yt8614_aneg_done(struct phy_device *phydev) ++static int yt8614_aneg_done(struct phy_device *phydev) + { ++ struct yt8xxx_priv *priv = phydev->priv; + int link_fiber = 0, link_utp = 0; + +- if (YT8614_PHY_MODE_CURR & YT_PHY_MODE_FIBER) { +- /* reading Fiber */ +- ytphy_write_ext(phydev, 0xa000, 3); +- link_fiber = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); +- } ++ if (priv->polling_mode & YT_PHY_MODE_FIBER) ++ link_fiber = yt861x_aneg_done_paged(phydev, ++ YT8614_REG_SPACE_SGMII); + +- if (YT8614_PHY_MODE_CURR & YT_PHY_MODE_UTP) { +- /* reading UTP */ +- ytphy_write_ext(phydev, 0xa000, 0); +- link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); +- } ++ if (priv->polling_mode & YT_PHY_MODE_UTP) ++ link_fiber = yt861x_aneg_done_paged(phydev, ++ YT8614_REG_SPACE_UTP); + + return !!(link_fiber | link_utp); + } + +-static int yt8614_read_status(struct phy_device *phydev) ++static int yt8614Q_aneg_done(struct phy_device *phydev) + { +- int ret; +- int val, yt8614_fiber_latch_val, yt8614_fiber_curr_val; +- int link; +- int link_utp = 0, link_fiber = 0; ++ struct yt8xxx_priv *priv = phydev->priv; ++ int link_fiber = 0; + +- if (YT8614_PHY_MODE_CURR & YT_PHY_MODE_UTP) { +- /* switch to utp and reading regs */ +- ret = ytphy_write_ext(phydev, 0xa000, 0); +- if (ret < 0) +- return ret; ++ if (priv->polling_mode & YT_PHY_MODE_FIBER) { ++ /* reading Fiber */ ++ link_fiber = yt861x_aneg_done_paged(phydev, ++ YT8614_REG_SPACE_SGMII); ++ } + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; ++ return !!(link_fiber); ++} + +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); +- if (link) { +- link_utp = 1; +- // here is same as 8521 and re-use the function; +- yt8521_adjust_status(phydev, val, 1); +- } else { +- link_utp = 0; +- } +- } ++static int yt861x_read_status_paged(struct phy_device *phydev, int reg_space, ++ int *status, int *lpa) ++{ ++ int latch_val, curr_val; ++ int ret = 0, oldpage; ++ int link; + +- if (YT8614_PHY_MODE_CURR & YT_PHY_MODE_FIBER) { +- /* reading Fiber/sgmii */ +- ret = ytphy_write_ext(phydev, 0xa000, 3); +- if (ret < 0) +- return ret; ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; ++ ret = *lpa = __phy_read(phydev, MII_LPA); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ ret = *status = __phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ ret = link = !!(*status & BIT(YTXXXX_LINK_STATUS_BIT)); + +- /* for fiber, from 1000m to 100m, there is not link down from 0x11, ++ if (YT8614_REG_SPACE_SGMII == reg_space) { ++ /* for fiber, from 1000m to 100m, ++ * there is not link down from 0x11, + * and check reg 1 to identify such case + */ +- yt8614_fiber_latch_val = phy_read(phydev, MII_BMSR); +- yt8614_fiber_curr_val = phy_read(phydev, MII_BMSR); +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); +- if (link && yt8614_fiber_latch_val != yt8614_fiber_curr_val) { +- link = 0; ++ latch_val = __phy_read(phydev, MII_BMSR); ++ curr_val = __phy_read(phydev, MII_BMSR); ++ if (link && latch_val != curr_val) { ++ ret = link = 0; + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->addr, yt8614_fiber_latch_val, yt8614_fiber_curr_val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", ++ __func__, phydev->addr, ++ latch_val, curr_val); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->mdio.addr, yt8614_fiber_latch_val, yt8614_fiber_curr_val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", ++ __func__, phydev->mdio.addr, ++ latch_val, curr_val); + #endif + } ++ } + +- if (link) { +- link_fiber = 1; +- yt8521_adjust_status(phydev, val, 0); +- } else { +- link_fiber = 0; +- } ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8614_read_status(struct phy_device *phydev) ++{ ++ struct yt8xxx_priv *priv = phydev->priv; ++ int link_utp = 0, link_fiber = 0; ++ int val; ++ int lpa; ++ ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ if (priv->polling_mode & YT_PHY_MODE_UTP) { ++ link_utp = yt861x_read_status_paged(phydev, ++ YT8614_REG_SPACE_UTP, &val, ++ &lpa); ++ if (link_utp < 0) ++ return link_utp; ++ ++ if (link_utp) ++ ytxxxx_adjust_status(phydev, val, 1); ++ ++ phydev->pause = !!(lpa & BIT(10)); ++ phydev->asym_pause = !!(lpa & BIT(11)); ++ } ++ ++ if (priv->polling_mode & YT_PHY_MODE_FIBER) { ++ link_fiber = yt861x_read_status_paged(phydev, ++ YT8614_REG_SPACE_SGMII, ++ &val, &lpa); ++ if (link_fiber < 0) ++ return link_fiber; ++ ++ if (link_fiber) ++ ytxxxx_adjust_status(phydev, val, 0); ++ ++ phydev->pause = !!(lpa & BIT(7)); ++ phydev->asym_pause = !!(lpa & BIT(8)); + } + + if (link_utp || link_fiber) { + if (phydev->link == 0) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media %s\n", +- __func__, phydev->addr, (link_utp && link_fiber) ? "both UTP and Fiber" : (link_utp ? "UTP" : "Fiber")); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media %s\n", ++ __func__, phydev->addr, ++ (link_utp && link_fiber) ? ++ "both UTP and Fiber" : ++ (link_utp ? "UTP" : "Fiber")); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media %s\n", +- __func__, phydev->mdio.addr, (link_utp && link_fiber) ? "both UTP and Fiber" : (link_utp ? "UTP" : "Fiber")); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media %s\n", ++ __func__, phydev->mdio.addr, ++ (link_utp && link_fiber) ? ++ "both UTP and Fiber" : ++ (link_utp ? "UTP" : "Fiber")); + #endif + phydev->link = 1; + } else { + if (phydev->link == 1) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->mdio.addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); + #endif + phydev->link = 0; + } + +- if (YT8614_PHY_MODE_CURR & YT_PHY_MODE_UTP) { ++ if (priv->polling_mode & YT_PHY_MODE_UTP) { + if (link_utp) +- ytphy_write_ext(phydev, 0xa000, 0); ++ ytphy_write_ext(phydev, YTPHY_REG_SMI_MUX, ++ YT8614_REG_SPACE_UTP); + } ++ + return 0; + } + +-static int yt8618_read_status(struct phy_device *phydev) ++static int yt8614Q_read_status(struct phy_device *phydev) + { +- int ret; +- /* maybe for 8614 yt8521_fiber_latch_val, yt8521_fiber_curr_val; */ ++ struct yt8xxx_priv *priv = phydev->priv; ++ int link_fiber = 0; + int val; +- int link; +- int link_utp = 0, link_fiber = 0; ++ int lpa; + +- /* switch to utp and reading regs */ +- ret = ytphy_write_ext(phydev, 0xa000, 0); +- if (ret < 0) +- return ret; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ if (priv->polling_mode & YT_PHY_MODE_FIBER) { ++ /* reading Fiber/sgmii */ ++ link_fiber = yt861x_read_status_paged(phydev, ++ YT8614_REG_SPACE_SGMII, ++ &val, &lpa); ++ if (link_fiber < 0) ++ return link_fiber; + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; ++ if (link_fiber) ++ ytxxxx_adjust_status(phydev, val, 0); + +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); +- if (link) { +- link_utp = 1; +- yt8521_adjust_status(phydev, val, 1); +- } else { +- link_utp = 0; ++ phydev->pause = !!(lpa & BIT(7)); ++ phydev->asym_pause = !!(lpa & BIT(8)); + } + +- if (link_utp || link_fiber) +- phydev->link = 1; +- else +- phydev->link = 0; +- +- return 0; +-} +- +-int yt8618_suspend(struct phy_device *phydev) +-{ +-#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) +- int value; +- +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_lock(&phydev->lock); ++ if (link_fiber) { ++ if (phydev->link == 0) ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media Fiber\n", ++ __func__, phydev->addr); + #else +- /* no need lock in 4.19 */ ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media Fiber\n", ++ __func__, phydev->mdio.addr); + #endif +- +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); +- +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_unlock(&phydev->lock); ++ phydev->link = 1; ++ } else { ++ if (phydev->link == 1) ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); + #else +- /* no need lock/unlock in 4.19 */ ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); + #endif +-#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ ++ phydev->link = 0; ++ } + + return 0; + } + +-int yt8618_resume(struct phy_device *phydev) ++static int yt8618_read_status(struct phy_device *phydev) + { +-#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) +- int value; ++ int link_utp; ++ int val; ++ int lpa; + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_lock(&phydev->lock); +-#else +- /* no need lock/unlock in 4.19 */ +-#endif ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ link_utp = yt861x_read_status_paged(phydev, ++ YT8614_REG_SPACE_UTP, &val, &lpa); ++ if (link_utp < 0) ++ return link_utp; + +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ if (link_utp) ++ ytxxxx_adjust_status(phydev, val, 1); + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_unlock(&phydev->lock); +-#else +- /* no need lock/unlock in 4.19 */ +-#endif +-#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ ++ phydev->pause = !!(lpa & BIT(10)); ++ phydev->asym_pause = !!(lpa & BIT(11)); + + return 0; + } + +-int yt8614_suspend(struct phy_device *phydev) ++static int yt8618_suspend(struct phy_device *phydev) + { + #if !(SYS_WAKEUP_BASED_ON_ETH_PKT) +- int value; +- +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_lock(&phydev->lock); +-#else +- /* no need lock in 4.19 */ +-#endif +- +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); +- +- ytphy_write_ext(phydev, 0xa000, 3); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ int ret; + +- ytphy_write_ext(phydev, 0xa000, 0); ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) ++ return ret; + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_unlock(&phydev->lock); +-#else +- /* no need lock/unlock in 4.19 */ +-#endif +-#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; + } + +-int yt8614_resume(struct phy_device *phydev) ++static int yt8618_resume(struct phy_device *phydev) + { + #if !(SYS_WAKEUP_BASED_ON_ETH_PKT) +- int value; +- +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_lock(&phydev->lock); +-#else +- /* no need lock/unlock in 4.19 */ +-#endif +- +- ytphy_write_ext(phydev, 0xa000, 0); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); +- +- ytphy_write_ext(phydev, 0xa000, 3); +- value = phy_read(phydev, MII_BMCR); +- phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ int ret; + +- ytphy_write_ext(phydev, 0xa000, 0); ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_UTP); ++ if (ret < 0) ++ return ret; + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +- mutex_unlock(&phydev->lock); +-#else +- /* no need lock/unlock in 4.19 */ +-#endif +-#endif /* !(SYS_WAKEUP_BASED_ON_ETH_PKT) */ ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_QSGMII); ++ if (ret < 0) ++ return ret; ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; + } + +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) +-#else +-int yt8821_soft_reset(struct phy_device *phydev) ++__attribute__((unused)) static int ++yt861x_suspend_paged(struct phy_device *phydev, int reg_space) + { +- int ret, val; ++ int ret = 0, oldpage; ++ int value; + +- val = ytphy_read_ext(phydev, 0xa001); +- ytphy_write_ext(phydev, 0xa001, (val & ~0x8000)); ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; + +- ytphy_write_ext(phydev, 0xa000, 0); +- ret = ytphy_soft_reset(phydev); ++ ret = value = __phy_read(phydev, MII_BMCR); ++ if (ret < 0) ++ goto err_restore_page; ++ ret = __phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); + +- return ret; ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); + } +-#endif + +-static int yt8821_init(struct phy_device *phydev) ++static int yt8614_suspend(struct phy_device *phydev) + { +- int ret = 0; +- int val = 0; ++#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) ++ int ret; + +- /* sds pll cfg */ +- ret = ytphy_write_ext(phydev, 0xa050, 0x1000); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0xa000, 0x2); ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_UTP); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x23, 0x47a1); ++ ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_SGMII); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0xbd, 0x3547); ++ ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_QSGMII); + if (ret < 0) + return ret; ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + +- /* wait 1s */ +- msleep(1000); ++ return 0; ++} + +- /* calibration dcc */ +- ret = ytphy_write_ext(phydev, 0xbd, 0xa547); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x29, 0x3003); +- if (ret < 0) +- return ret; ++static int yt8614Q_suspend(struct phy_device *phydev) ++{ ++#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) ++ int ret; + +- /* sds driver swing */ +- ret = ytphy_write_ext(phydev, 0x25, 0x788); ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_SGMII); + if (ret < 0) + return ret; + +- /* phy cfg */ +- ret = ytphy_write_ext(phydev, 0xa000, 0x0); ++ ret = yt861x_suspend_paged(phydev, YT8614_REG_SPACE_QSGMII); + if (ret < 0) + return ret; ++#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + +- /* phy template cfg */ +- ret = ytphy_write_ext(phydev, 0x471, 0x4545); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x476, 0x4848); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x477, 0x4848); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x478, 0x4848); ++ return 0; ++} ++ ++__attribute__((unused)) static int ++yt861x_resume_paged(struct phy_device *phydev, int reg_space) ++{ ++ int ret = 0, oldpage; ++ int value; ++ ++ oldpage = ytphy_select_page(phydev, reg_space); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ ret = value = __phy_read(phydev, MII_BMCR); + if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x479, 0x4848); ++ goto err_restore_page; ++ ret = __phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); ++ ++err_restore_page: ++ return ytphy_restore_page(phydev, oldpage, ret); ++} ++ ++static int yt8614_resume(struct phy_device *phydev) ++{ ++#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) ++ int ret; ++ ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_UTP); + if (ret < 0) + return ret; + +- /* calibrate phy lc pll */ +- ret = ytphy_write_ext(phydev, 0x600, 0x2300); ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_SGMII); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x8, 0x8041); ++ ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_QSGMII); + if (ret < 0) + return ret; ++#endif /* !(SYS_WAKEUP_BASED_ON_ETH_PKT) */ ++ ++ return 0; ++} ++ ++static int yt8614Q_resume(struct phy_device *phydev) ++{ ++#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) ++ int ret; + +- /* prm_small_lng/med */ +- ret = ytphy_write_ext(phydev, 0x388, 0x90); ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_SGMII); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x387, 0x90); ++ ++ ret = yt861x_resume_paged(phydev, YT8614_REG_SPACE_QSGMII); + if (ret < 0) + return ret; ++#endif /* !(SYS_WAKEUP_BASED_ON_ETH_PKT) */ ++ ++ return 0; ++} ++ ++static int ytxxxx_soft_reset(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ val = ytphy_read_ext(phydev, 0xa001); ++ ytphy_write_ext(phydev, 0xa001, (val & ~0x8000)); ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 0); ++ ++ return ret; ++} ++ ++static int yt8821_init(struct phy_device *phydev) ++{ ++ int ret = 0; + +- /* echo_delay_cfg */ +- ret = ytphy_write_ext(phydev, 0x3, 0xa026); ++ ret = ytphy_write_ext(phydev, 0xa000, 0x2); + if (ret < 0) + return ret; + +- /* pbo setting */ +- ret = ytphy_write_ext(phydev, 0x47e, 0x3535); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x47f, 0x3535); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x480, 0x3535); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x481, 0x3535); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x483, 0x2a2a); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x484, 0x2a2a); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x485, 0x2a2a); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x486, 0x2a2a); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x488, 0x2121); +- if (ret < 0) +- return ret; +- ret = ytphy_write_ext(phydev, 0x489, 0x2121); ++ ret = ytphy_write_ext(phydev, 0x23, 0x8605); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x48a, 0x2121); ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 0x0); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x48b, 0x2121); ++ ++ ret = ytphy_write_ext(phydev, 0x34e, 0x8080); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x48d, 0x1a1a); ++ ++ ret = ytphy_write_ext(phydev, 0x4d2, 0x5200); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x48e, 0x1a1a); ++ ++ ret = ytphy_write_ext(phydev, 0x4d3, 0x5200); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x48f, 0x1a1a); ++ ++ ret = ytphy_write_ext(phydev, 0x372, 0x5a3c); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x490, 0x1a1a); ++ ++ ret = ytphy_write_ext(phydev, 0x374, 0x7c6c); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x492, 0x1515); ++ ++ ret = ytphy_write_ext(phydev, 0x336, 0xaa0a); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x493, 0x1515); ++ ++ ret = ytphy_write_ext(phydev, 0x340, 0x3022); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x494, 0x1515); ++ ++ ret = ytphy_write_ext(phydev, 0x36a, 0x8000); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x495, 0x1515); ++ ++ ret = ytphy_write_ext(phydev, 0x4b3, 0x7711); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x497, 0x1111); ++ ++ ret = ytphy_write_ext(phydev, 0x4b5, 0x2211); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x498, 0x1111); ++ ++ ret = ytphy_write_ext(phydev, 0x56, 0x20); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x499, 0x1111); ++ ++ ret = ytphy_write_ext(phydev, 0x56, 0x3f); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x49a, 0x1111); ++ ++ ret = ytphy_write_ext(phydev, 0x97, 0x380c); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x49c, 0x0d0d); ++ ++ ret = ytphy_write_ext(phydev, 0x660, 0x112a); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x49d, 0x0d0d); ++ ++ ret = ytphy_write_ext(phydev, 0x450, 0xe9); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x49e, 0x0d0d); ++ ++ ret = ytphy_write_ext(phydev, 0x466, 0x6464); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0x49f, 0x0d0d); ++ ++ ret = ytphy_write_ext(phydev, 0x467, 0x6464); + if (ret < 0) + return ret; +- ret = ytphy_write_ext(phydev, 0xa052, 0x7); ++ ++ ret = ytphy_write_ext(phydev, 0x468, 0x6464); + if (ret < 0) + return ret; + +- /* fast link down cfg */ +- ret = ytphy_write_ext(phydev, 0x355, 0x7d07); ++ ret = ytphy_write_ext(phydev, 0x469, 0x6464); + if (ret < 0) + return ret; + +- /* soft reset */ +- val = phy_read(phydev, MII_BMCR); +- if (val < 0) +- return val; +- ret = phy_write(phydev, MII_BMCR, val | BMCR_RESET); +- + return ret; + } + + static int yt8821_config_init(struct phy_device *phydev) + { +- int ret; +- int val, hw_strap_mode; ++ int ret, val; + + phydev->irq = PHY_POLL; + +- /* NOTE: this function should not be called more than one for each chip. */ +- hw_strap_mode = ytphy_read_ext(phydev, 0xa001) & 0x7; ++ val = ytphy_read_ext(phydev, 0xa001); ++ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { ++ val &= ~(BIT(0)); ++ val &= ~(BIT(1)); ++ val &= ~(BIT(2)); ++ ret = ytphy_write_ext(phydev, 0xa001, val); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 2); ++ if (ret < 0) ++ return ret; + +- ytphy_write_ext(phydev, 0xa000, 0); +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) +- ret = ytphy_config_init(phydev); +-#else +- ret = genphy_config_init(phydev); +-#endif +- if (ret < 0) +- return ret; ++ val = phy_read(phydev, MII_BMCR); ++ val |= BIT(YTXXXX_AUTO_NEGOTIATION_BIT); ++ phy_write(phydev, MII_BMCR, val); ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 0x0); ++ if (ret < 0) ++ return ret; ++ } ++#if (KERNEL_VERSION(4, 10, 17) < LINUX_VERSION_CODE) ++ else if (phydev->interface == PHY_INTERFACE_MODE_2500BASEX) ++ { ++ val |= BIT(0); ++ val &= ~(BIT(1)); ++ val &= ~(BIT(2)); ++ ret = ytphy_write_ext(phydev, 0xa001, val); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 0x0); ++ if (ret < 0) ++ return ret; ++ ++ val = phy_read(phydev, MII_ADVERTISE); ++ val |= BIT(YTXXXX_PAUSE_BIT); ++ val |= BIT(YTXXXX_ASYMMETRIC_PAUSE_BIT); ++ phy_write(phydev, MII_ADVERTISE, val); ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 2); ++ if (ret < 0) ++ return ret; ++ ++ val = phy_read(phydev, MII_ADVERTISE); ++ val |= BIT(YT8821_SDS_PAUSE_BIT); ++ val |= BIT(YT8821_SDS_ASYMMETRIC_PAUSE_BIT); ++ phy_write(phydev, MII_ADVERTISE, val); ++ ++ val = phy_read(phydev, MII_BMCR); ++ val &= (~BIT(YTXXXX_AUTO_NEGOTIATION_BIT)); ++ phy_write(phydev, MII_BMCR, val); ++ ++ ret = ytphy_write_ext(phydev, 0xa000, 0x0); ++ if (ret < 0) ++ return ret; ++ } ++#endif ++ else ++ { ++ val |= BIT(0); ++ val &= ~(BIT(1)); ++ val |= BIT(2); ++ ret = ytphy_write_ext(phydev, 0xa001, val); ++ if (ret < 0) ++ return ret; ++ } + + ret = yt8821_init(phydev); + if (ret < 0) +@@ -1938,41 +3091,75 @@ static int yt8821_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + ++ /* soft reset */ ++ ytxxxx_soft_reset(phydev); ++ + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, strap mode = %d\n", __func__, phydev->addr, hw_strap_mode); ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->addr); + #else +- netdev_info(phydev->attached_dev, "%s done, phy addr: %d, strap mode = %d\n", __func__, phydev->mdio.addr, hw_strap_mode); ++ netdev_info(phydev->attached_dev, "%s done, phy addr: %d\n", ++ __func__, phydev->mdio.addr); + #endif + + return ret; + } + +-/* for fiber mode, there is no 10M speed mode and +- * this function is for this purpose. +- */ +-static int yt8821_adjust_status(struct phy_device *phydev, int val, int is_utp) ++#if (KERNEL_VERSION(6, 0, 19) < LINUX_VERSION_CODE) ++static int yt8821_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ int val; ++ ++ val = ytphy_read_ext(phydev, 0xa001); ++ if (val < 0) ++ return val; ++ ++ if (val & (BIT(2) | BIT(1) | BIT(0))) ++ return RATE_MATCH_PAUSE; ++ ++ return RATE_MATCH_NONE; ++} ++#endif ++ ++static int yt8821_aneg_done(struct phy_device *phydev) ++{ ++ int link_utp = 0; ++ ++ /* reading UTP */ ++ ytphy_write_ext(phydev, 0xa000, 0); ++ link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(10))); ++ ++#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) ++ netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_utp: %d\n", ++ __func__, phydev->addr, link_utp); ++#else ++ netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_utp: %d\n", ++ __func__, phydev->mdio.addr, link_utp); ++#endif ++ ++ return !!(link_utp); ++} ++static int yt8821_adjust_status(struct phy_device *phydev, int val) + { +- int speed_mode, duplex; + int speed_mode_bit15_14, speed_mode_bit9; ++ int speed_mode, duplex; + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) + int speed = -1; + #else + int speed = SPEED_UNKNOWN; + #endif + +- if (is_utp) +- duplex = (val & YT8512_DUPLEX) >> YT8521_DUPLEX_BIT; +- else +- duplex = 1; ++ duplex = (val & YTXXXX_DUPLEX) >> YTXXXX_DUPLEX_BIT; + +- /* Bit9-Bit15-Bit14 speed mode 100---2.5G; 010---1000M; 001---100M; 000---10M */ +- speed_mode_bit15_14 = (val & YT8521_SPEED_MODE) >> YT8521_SPEED_MODE_BIT; ++ /* Bit9-Bit15-Bit14 speed mode 100-2.5G; 010-1000M; 001-100M; 000-10M */ ++ speed_mode_bit15_14 = (val & YTXXXX_SPEED_MODE) >> ++ YTXXXX_SPEED_MODE_BIT; + speed_mode_bit9 = (val & BIT(9)) >> 9; + speed_mode = (speed_mode_bit9 << 2) | speed_mode_bit15_14; + switch (speed_mode) { + case 0: +- if (is_utp) +- speed = SPEED_10; ++ speed = SPEED_10; + break; + case 1: + speed = SPEED_100; +@@ -2000,324 +3187,443 @@ static int yt8821_adjust_status(struct phy_device *phydev, int val, int is_utp) + + static int yt8821_read_status(struct phy_device *phydev) + { ++ int link_utp = 0; ++ int link; + int ret; + int val; +- int yt8521_fiber_latch_val; +- int yt8521_fiber_curr_val; +- int link; +- int link_utp = 0, link_fiber = 0; +- +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { +- /* reading UTP */ +- ret = ytphy_write_ext(phydev, 0xa000, 0); +- if (ret < 0) +- return ret; +- +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; +- +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); +- if (link) { +- link_utp = 1; +- yt8821_adjust_status(phydev, val, 1); /* speed(2500), duplex */ +- } else { +- link_utp = 0; +- } +- } //(YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) +- +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) { +- /* reading Fiber */ +- ret = ytphy_write_ext(phydev, 0xa000, 2); +- if (ret < 0) +- return ret; + +- val = phy_read(phydev, REG_PHY_SPEC_STATUS); +- if (val < 0) +- return val; ++ /* reading UTP */ ++ ret = ytphy_write_ext(phydev, 0xa000, 0); ++ if (ret < 0) ++ return ret; + +- //note: below debug information is used to check multiple PHy ports. ++ genphy_read_status(phydev); + +- /* for fiber, from 1000m to 100m, there is not link down from 0x11, +- * and check reg 1 to identify such case this is important for Linux +- * kernel for that, missing linkdown event will cause problem. +- */ +- yt8521_fiber_latch_val = phy_read(phydev, MII_BMSR); +- yt8521_fiber_curr_val = phy_read(phydev, MII_BMSR); +- link = val & (BIT(YT8521_LINK_STATUS_BIT)); +- if (link && yt8521_fiber_latch_val != yt8521_fiber_curr_val) { +- link = 0; +-#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->addr, yt8521_fiber_latch_val, yt8521_fiber_curr_val); +-#else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", +- __func__, phydev->mdio.addr, yt8521_fiber_latch_val, yt8521_fiber_curr_val); +-#endif +- } ++ val = phy_read(phydev, REG_PHY_SPEC_STATUS); ++ if (val < 0) ++ return val; + +- if (link) { +- link_fiber = 1; +- yt8821_adjust_status(phydev, val, 0); +- } else { +- link_fiber = 0; +- } +- } //(YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) ++ link = val & (BIT(YTXXXX_LINK_STATUS_BIT)); ++ if (link) { ++ link_utp = 1; ++ /* speed(2500), duplex */ ++ yt8821_adjust_status(phydev, val); ++ } else { ++ link_utp = 0; ++ } + +- if (link_utp || link_fiber) { ++ if (link_utp) { + if (phydev->link == 0) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", +- __func__, phydev->addr, (link_utp && link_fiber) ? "UNKNOWN MEDIA" : (link_utp ? "UTP" : "Fiber"), (unsigned int)val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->addr, (unsigned int)val); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", +- __func__, phydev->mdio.addr, (link_utp && link_fiber) ? "UNKNOWN MEDIA" : (link_utp ? "UTP" : "Fiber"), (unsigned int)val); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link up, media: UTP, mii reg 0x11 = 0x%x\n", ++ __func__, phydev->mdio.addr, ++ (unsigned int)val); + #endif + phydev->link = 1; + } else { + if (phydev->link == 1) + #if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->addr); + #else +- netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", __func__, phydev->mdio.addr); ++ netdev_info(phydev->attached_dev, ++ "%s, phy addr: %d, link down\n", ++ __func__, phydev->mdio.addr); + #endif + + phydev->link = 0; + } + +- if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { +- if (link_fiber) +- ytphy_write_ext(phydev, 0xa000, 2); +- if (link_utp) +- ytphy_write_ext(phydev, 0xa000, 0); ++ if (link_utp) ++ ytphy_write_ext(phydev, 0xa000, 0); ++ ++#if (KERNEL_VERSION(4, 10, 17) < LINUX_VERSION_CODE) ++ val = ytphy_read_ext(phydev, 0xa001); ++ if ((val & (BIT(2) | BIT(1) | BIT(0))) == 0x0) { ++ switch (phydev->speed) { ++ case SPEED_2500: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ case SPEED_1000: ++ case SPEED_100: ++ case SPEED_10: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ } + } ++#endif ++ + return 0; + } + +-#if (KERNEL_VERSION(5, 1, 21) < LINUX_VERSION_CODE) ++#if (KERNEL_VERSION(5, 0, 21) < LINUX_VERSION_CODE) + static int yt8821_get_features(struct phy_device *phydev) + { +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, 1); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->supported, 1); + return genphy_read_abilities(phydev); + } + #endif + ++static int ytxxxx_suspend(struct phy_device *phydev) ++{ ++ int wol_enabled = 0; ++ int value = 0; ++ ++#if (YTPHY_WOL_FEATURE_ENABLE) ++ value = phy_read(phydev, YTPHY_UTP_INTR_REG); ++ wol_enabled = value & YTPHY_WOL_FEATURE_INTR; ++#endif ++ ++ if (!wol_enabled) { ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); ++ } ++ ++ return 0; ++} ++ ++static int ytxxxx_resume(struct phy_device *phydev) ++{ ++ int value; ++ ++ value = phy_read(phydev, MII_BMCR); ++ value &= ~BMCR_PDOWN; ++ value &= ~BMCR_ISOLATE; ++ ++ phy_write(phydev, MII_BMCR, value); ++ ++ return 0; ++} ++ + static struct phy_driver ytphy_drvs[] = { + { +- .phy_id = PHY_ID_YT8010, +- .name = "YT8010 Automotive Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_BASIC_FEATURES, +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ .phy_id = PHY_ID_YT8010, ++ .name = "YT8010 100M Automotive Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8010_soft_reset, ++ .soft_reset = yt8010_soft_reset, + #endif +- .config_aneg = yt8010_config_aneg, ++ .config_aneg = yt8010_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8010_aneg_done, ++ .aneg_done = yt8010_aneg_done, + #endif +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) +- .config_init = ytphy_config_init, ++ .config_init = yt8010_config_init, ++ .read_status = yt8010_read_status, ++ }, { ++ .phy_id = PHY_ID_YT8010AS, ++ .name = "YT8010AS 100M Automotive Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .config_init = genphy_config_init, ++ .soft_reset = yt8010AS_soft_reset, + #endif +- .read_status = yt8010_read_status, ++ .config_aneg = yt8010_config_aneg, ++#if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) ++ .aneg_done = yt8010_aneg_done, ++#endif ++ .config_init = yt8010AS_config_init, ++ .read_status = yt8010_read_status, + }, { +- .phy_id = PHY_ID_YT8010AS, +- .name = "YT8010AS Automotive Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_BASIC_FEATURES, +- .flags = PHY_POLL, ++ .phy_id = PHY_ID_YT8011, ++ .name = "YT8011 Automotive Gigabit Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8011_probe, + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8010AS_soft_reset, ++ .soft_reset = yt8011_soft_reset, + #endif ++ .config_aneg = yt8011_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8010_aneg_done, ++ .aneg_done = yt8011_aneg_done, + #endif +- .config_init = yt8010AS_config_init, +- .read_status = yt8010_read_status, ++ .config_init = yt8011_config_init, ++ .read_status = yt8011_read_status, + }, { +- .phy_id = PHY_ID_YT8510, +- .name = "YT8510 100/10Mb Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_BASIC_FEATURES, +- .flags = PHY_POLL, +- .config_aneg = genphy_config_aneg, ++ .phy_id = PHY_ID_YT8510, ++ .name = "YT8510 100M Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) +- .config_init = ytphy_config_init, ++ .config_init = ytphy_config_init, + #else +- .config_init = genphy_config_init, ++ .config_init = genphy_config_init, + #endif +- .read_status = genphy_read_status, ++ .read_status = genphy_read_status, + }, { +- .phy_id = PHY_ID_YT8511, +- .name = "YT8511 Gigabit Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +- .config_aneg = genphy_config_aneg, ++ .phy_id = PHY_ID_YT8511, ++ .name = "YT8511 Gigabit Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_aneg = genphy_config_aneg, + #if GMAC_CLOCK_INPUT_NEEDED +- .config_init = yt8511_config_init, ++ .config_init = yt8511_config_init, + #else + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) || (KERNEL_VERSION(5, 3, 0) < LINUX_VERSION_CODE) +- .config_init = ytphy_config_init, ++ .config_init = ytphy_config_init, + #else +- .config_init = genphy_config_init, ++ .config_init = genphy_config_init, + #endif + #endif +- .read_status = genphy_read_status, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .read_status = genphy_read_status, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { +- .phy_id = PHY_ID_YT8512, +- .name = "YT8512 Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_BASIC_FEATURES, +- .flags = PHY_POLL, +- .config_aneg = genphy_config_aneg, +- .config_init = yt8512_config_init, +- .read_status = yt8512_read_status, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .phy_id = PHY_ID_YT8512, ++ .name = "YT8512 100M Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_aneg = genphy_config_aneg, ++ .config_init = yt8512_config_init, ++ .probe = yt8512_probe, ++ .read_status = yt8512_read_status, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { +- .phy_id = PHY_ID_YT8512B, +- .name = "YT8512B Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_BASIC_FEATURES, +- .flags = PHY_POLL, +- .config_aneg = genphy_config_aneg, +- .config_init = yt8512_config_init, +- .read_status = yt8512_read_status, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .phy_id = PHY_ID_YT8522, ++ .name = "YT8522 100M Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8522_probe, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_aneg = genphy_config_aneg, ++ .config_init = yt8522_config_init, ++ .read_status = yt8522_read_status, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { +- .phy_id = PHY_ID_YT8521, +- .name = "YT8521 Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ .phy_id = PHY_ID_YT8521, ++ .name = "YT8521 Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8521_probe, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8521_soft_reset, ++ .soft_reset = ytxxxx_soft_reset, + #endif +- .config_aneg = genphy_config_aneg, ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8521_aneg_done, ++ .aneg_done = yt8521_aneg_done, + #endif +- .config_init = yt8521_config_init, +- .read_status = yt8521_read_status, +- .suspend = yt8521_suspend, +- .resume = yt8521_resume, ++ .config_init = yt8521_config_init, ++ .read_status = yt8521_read_status, ++ .suspend = yt8521_suspend, ++ .resume = yt8521_resume, + #if (YTPHY_WOL_FEATURE_ENABLE) +- .get_wol = &ytphy_wol_feature_get, +- .set_wol = &ytphy_wol_feature_set, ++ .get_wol = &ytphy_wol_feature_get, ++ .set_wol = &ytphy_wol_feature_set, + #endif + }, { + /* same as 8521 */ +- .phy_id = PHY_ID_YT8531S, +- .name = "YT8531S Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ .phy_id = PHY_ID_YT8531S, ++ .name = "YT8531S Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8521_probe, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8521_soft_reset, ++ .soft_reset = ytxxxx_soft_reset, + #endif +- .config_aneg = genphy_config_aneg, ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8521_aneg_done, ++ .aneg_done = yt8521_aneg_done, + #endif +- .config_init = yt8531S_config_init, +- .read_status = yt8521_read_status, +- .suspend = yt8521_suspend, +- .resume = yt8521_resume, ++ .config_init = yt8531S_config_init, ++ .read_status = yt8521_read_status, ++ .suspend = yt8521_suspend, ++ .resume = yt8521_resume, + #if (YTPHY_WOL_FEATURE_ENABLE) +- .get_wol = &ytphy_wol_feature_get, +- .set_wol = &ytphy_wol_feature_set, ++ .get_wol = &ytphy_wol_feature_get, ++ .set_wol = &ytphy_wol_feature_set, + #endif + }, { + /* same as 8511 */ +- .phy_id = PHY_ID_YT8531, +- .name = "YT8531 Gigabit Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +- .config_aneg = genphy_config_aneg, +- +- .config_init = yt8531_config_init, +- .read_status = genphy_read_status, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .phy_id = PHY_ID_YT8531, ++ .name = "YT8531 Gigabit Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .config_aneg = genphy_config_aneg, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_init = yt8531_config_init, ++ .read_status = genphy_read_status, ++#if (KERNEL_VERSION(5, 0, 21) < LINUX_VERSION_CODE) ++ .link_change_notify = ytphy_link_change_notify, ++#endif ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + #if (YTPHY_WOL_FEATURE_ENABLE) +- .get_wol = &ytphy_wol_feature_get, +- .set_wol = &ytphy_wol_feature_set, ++ .get_wol = &ytphy_wol_feature_get, ++ .set_wol = &ytphy_wol_feature_set, + #endif +- }, { +- .phy_id = PHY_ID_YT8618, +- .name = "YT8618 Ethernet", +- .phy_id_mask = MOTORCOMM_MPHY_ID_MASK, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ }, ++#ifdef YTPHY_YT8543_ENABLE ++ { ++ .phy_id = PHY_ID_YT8543, ++ .name = "YT8543 Dual Port Gigabit Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .config_aneg = genphy_config_aneg, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = ytphy_soft_reset, ++#endif ++ .config_init = yt8543_config_init, ++ .read_status = yt8543_read_status, ++ .suspend = ytxxxx_suspend, ++ .resume = ytxxxx_resume, ++#if (YTPHY_WOL_FEATURE_ENABLE) ++ .get_wol = &ytphy_wol_feature_get, ++ .set_wol = &ytphy_wol_feature_set, ++#endif ++ }, ++#endif ++ { ++ .phy_id = PHY_ID_YT8618, ++ .name = "YT8618 Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8618_soft_reset, ++ .soft_reset = yt8618_soft_reset, + #endif +- .config_aneg = genphy_config_aneg, ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8618_aneg_done, ++ .aneg_done = yt8618_aneg_done, + #endif +- .config_init = yt8618_config_init, +- .read_status = yt8618_read_status, +- .suspend = yt8618_suspend, +- .resume = yt8618_resume, ++ .config_init = yt8618_config_init, ++ .read_status = yt8618_read_status, ++ .suspend = yt8618_suspend, ++ .resume = yt8618_resume, + }, + { +- .phy_id = PHY_ID_YT8614, +- .name = "YT8614 Ethernet", +- .phy_id_mask = MOTORCOMM_MPHY_ID_MASK_8614, +- .features = PHY_GBIT_FEATURES, +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ .phy_id = PHY_ID_YT8614, ++ .name = "YT8614 Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8614_probe, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8614_soft_reset, ++ .soft_reset = yt8614_soft_reset, + #endif +- .config_aneg = genphy_config_aneg, ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8614_aneg_done, ++ .aneg_done = yt8614_aneg_done, + #endif +- .config_init = yt8614_config_init, +- .read_status = yt8614_read_status, +- .suspend = yt8614_suspend, +- .resume = yt8614_resume, ++ .config_init = yt8614_config_init, ++ .read_status = yt8614_read_status, ++ .suspend = yt8614_suspend, ++ .resume = yt8614_resume, + }, + { +- .phy_id = PHY_ID_YT8821, +- .name = "YT8821 2.5Gb Ethernet", +- .phy_id_mask = MOTORCOMM_PHY_ID_MASK_8821, +-#if (KERNEL_VERSION(5, 2, 0) > LINUX_VERSION_CODE) +- .features = PHY_GBIT_FEATURES, ++ .phy_id = PHY_ID_YT8614Q, ++ .name = "YT8614Q Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_POLL, ++ .probe = yt8614Q_probe, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) ++#else ++ .soft_reset = yt8614Q_soft_reset, + #endif +- .flags = PHY_POLL, +-#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) ++ .config_aneg = yt8614Q_config_aneg, ++#if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) ++ .aneg_done = yt8614Q_aneg_done, ++#endif ++ .config_init = yt8614Q_config_init, ++ .read_status = yt8614Q_read_status, ++ .suspend = yt8614Q_suspend, ++ .resume = yt8614Q_resume, ++ }, ++ { ++ .phy_id = PHY_ID_YT8821, ++ .name = "YT8821 2.5Gbps Ethernet", ++ .phy_id_mask = MOTORCOMM_PHY_ID_MASK, ++#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) ++ .features = PHY_GBIT_FEATURES, ++#endif ++ .flags = PHY_POLL, ++#if (KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE) + #else +- .soft_reset = yt8821_soft_reset, ++ .soft_reset = ytxxxx_soft_reset, + #endif +- .config_aneg = genphy_config_aneg, ++ .config_aneg = genphy_config_aneg, + #if (KERNEL_VERSION(3, 14, 79) < LINUX_VERSION_CODE) +- .aneg_done = yt8521_aneg_done, ++ .aneg_done = yt8821_aneg_done, ++#endif ++#if (KERNEL_VERSION(5, 0, 21) < LINUX_VERSION_CODE) ++ .get_features = yt8821_get_features, ++#endif ++ .config_init = yt8821_config_init, ++#if (YTPHY_WOL_FEATURE_ENABLE) ++ .set_wol = &ytphy_wol_feature_set, ++ .get_wol = &ytphy_wol_feature_get, + #endif +-#if (KERNEL_VERSION(5, 1, 21) < LINUX_VERSION_CODE) +- .get_features = yt8821_get_features, ++#if (KERNEL_VERSION(6, 0, 19) < LINUX_VERSION_CODE) ++ .get_rate_matching = yt8821_get_rate_matching, + #endif +- .config_init = yt8821_config_init, +- .read_status = yt8821_read_status, +- .suspend = yt8521_suspend, +- .resume = yt8521_resume, ++ .read_status = yt8821_read_status, ++ .suspend = ytxxxx_suspend, ++ .resume = ytxxxx_resume, + }, + }; + ++static ssize_t phydrv_ver(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) { ++ char buf[64]; ++ int len; ++ ++ len = snprintf(buf, sizeof(buf), "Driver Version: %s\n", ++ YTPHY_LINUX_VERSION); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++/* File operations */ ++static const struct file_operations ver_fops = { ++ .read = phydrv_ver, ++}; ++ + #if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE) + static int ytphy_drivers_register(struct phy_driver *phy_drvs, int size) + { +@@ -2333,8 +3639,8 @@ static int ytphy_drivers_register(struct phy_driver *phy_drvs, int size) + return 0; + + err: +- for (j = 0; j < i; j++) +- phy_driver_unregister(&phy_drvs[j]); ++ for (j = 0; j < i; j++) ++ phy_driver_unregister(&phy_drvs[j]); + + return ret; + } +@@ -2349,37 +3655,87 @@ static void ytphy_drivers_unregister(struct phy_driver *phy_drvs, int size) + + static int __init ytphy_init(void) + { ++ /* Create debugfs directory */ ++ dir = debugfs_create_dir(MODULE_NAME, NULL); ++ if (!dir) { ++ pr_err(MODULE_NAME ": Failed to create debugfs directory\n"); ++ return -ENOMEM; ++ } ++ ++ /* Create debugfs file */ ++ if (!debugfs_create_file(PHYDRV_VER, 0444, dir, NULL, &ver_fops)) { ++ pr_err(MODULE_NAME ": Failed to create debugfs file\n"); ++ debugfs_remove(dir); ++ return -ENOMEM; ++ } ++ + return ytphy_drivers_register(ytphy_drvs, ARRAY_SIZE(ytphy_drvs)); + } + + static void __exit ytphy_exit(void) + { ++ debugfs_remove_recursive(dir); ++ pr_info(MODULE_NAME ": Module unloaded\n"); + ytphy_drivers_unregister(ytphy_drvs, ARRAY_SIZE(ytphy_drvs)); + } + + module_init(ytphy_init); + module_exit(ytphy_exit); + #else +-/* for linux 4.x */ +-module_phy_driver(ytphy_drvs); ++/* for linux 4.x ~ */ ++/* module_phy_driver(ytphy_drvs);*/ ++static int __init phy_module_init(void) ++{ ++ dir = debugfs_create_dir(MODULE_NAME, NULL); ++ if (!dir) { ++ pr_err(MODULE_NAME ": Failed to create debugfs directory\n"); ++ return -ENOMEM; ++ } ++ ++ /* Create debugfs file */ ++ if (!debugfs_create_file(PHYDRV_VER, 0444, dir, NULL, &ver_fops)) { ++ pr_err(MODULE_NAME ": Failed to create debugfs file\n"); ++ debugfs_remove(dir); ++ return -ENOMEM; ++ } ++ ++ return phy_drivers_register(ytphy_drvs, ARRAY_SIZE(ytphy_drvs), ++ THIS_MODULE); ++} ++static void __exit phy_module_exit(void) ++{ ++ debugfs_remove_recursive(dir); ++ pr_info(MODULE_NAME ": Module unloaded\n"); ++ ++ phy_drivers_unregister(ytphy_drvs, ARRAY_SIZE(ytphy_drvs)); ++} ++ ++module_init(phy_module_init); ++module_exit(phy_module_exit); + #endif + + MODULE_DESCRIPTION("Motorcomm PHY driver"); ++MODULE_VERSION(YTPHY_LINUX_VERSION); /* for modinfo xxxx.ko in userspace */ + MODULE_AUTHOR("Leilei Zhao"); + MODULE_LICENSE("GPL"); + + static struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_YT8010, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8010AS, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8510, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8511, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8512, MOTORCOMM_PHY_ID_MASK }, +- { PHY_ID_YT8512B, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8522, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8521, MOTORCOMM_PHY_ID_MASK }, +- { PHY_ID_YT8531S, MOTORCOMM_PHY_ID_8531_MASK }, +- { PHY_ID_YT8531, MOTORCOMM_PHY_ID_8531_MASK }, +- { PHY_ID_YT8618, MOTORCOMM_MPHY_ID_MASK }, +- { PHY_ID_YT8614, MOTORCOMM_MPHY_ID_MASK_8614 }, +- { PHY_ID_YT8821, MOTORCOMM_PHY_ID_MASK_8821 }, ++ { PHY_ID_YT8531S, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8531, MOTORCOMM_PHY_ID_MASK }, ++#ifdef YTPHY_YT8543_ENABLE ++ { PHY_ID_YT8543, MOTORCOMM_PHY_ID_MASK }, ++#endif ++ { PHY_ID_YT8614, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8614Q, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8618, MOTORCOMM_PHY_ID_MASK }, ++ { PHY_ID_YT8821, MOTORCOMM_PHY_ID_MASK }, + { } + }; + +diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig +index e3d7cb6c1290..cffad1c01249 100644 +--- a/drivers/net/wireless/realtek/rtw88/Kconfig ++++ b/drivers/net/wireless/realtek/rtw88/Kconfig +@@ -16,6 +16,12 @@ config RTW88_CORE + config RTW88_PCI + tristate + ++config RTW88_SDIO ++ tristate ++ ++config RTW88_USB ++ tristate ++ + config RTW88_8822B + tristate + +@@ -39,6 +45,28 @@ config RTW88_8822BE + + 802.11ac PCIe wireless network adapter + ++config RTW88_8822BS ++ tristate "Realtek 8822BS SDIO wireless network adapter" ++ depends on MMC ++ select RTW88_CORE ++ select RTW88_SDIO ++ select RTW88_8822B ++ help ++ Select this option will enable support for 8822BS chipset ++ ++ 802.11ac SDIO wireless network adapter ++ ++config RTW88_8822BU ++ tristate "Realtek 8822BU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8822B ++ help ++ Select this option will enable support for 8822BU chipset ++ ++ 802.11ac USB wireless network adapter ++ + config RTW88_8822CE + tristate "Realtek 8822CE PCI wireless network adapter" + depends on PCI +@@ -50,6 +78,28 @@ config RTW88_8822CE + + 802.11ac PCIe wireless network adapter + ++config RTW88_8822CS ++ tristate "Realtek 8822CS SDIO wireless network adapter" ++ depends on MMC ++ select RTW88_CORE ++ select RTW88_SDIO ++ select RTW88_8822C ++ help ++ Select this option will enable support for 8822CS chipset ++ ++ 802.11ac SDIO wireless network adapter ++ ++config RTW88_8822CU ++ tristate "Realtek 8822CU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8822C ++ help ++ Select this option will enable support for 8822CU chipset ++ ++ 802.11ac USB wireless network adapter ++ + config RTW88_8723DE + tristate "Realtek 8723DE PCI wireless network adapter" + depends on PCI +@@ -61,6 +111,28 @@ config RTW88_8723DE + + 802.11n PCIe wireless network adapter + ++config RTW88_8723DS ++ tristate "Realtek 8723DS SDIO wireless network adapter" ++ depends on MMC ++ select RTW88_CORE ++ select RTW88_SDIO ++ select RTW88_8723D ++ help ++ Select this option will enable support for 8723DS chipset ++ ++ 802.11n SDIO wireless network adapter ++ ++config RTW88_8723DU ++ tristate "Realtek 8723DU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8723D ++ help ++ Select this option will enable support for 8723DU chipset ++ ++ 802.11n USB wireless network adapter ++ + config RTW88_8821CE + tristate "Realtek 8821CE PCI wireless network adapter" + depends on PCI +@@ -72,6 +144,28 @@ config RTW88_8821CE + + 802.11ac PCIe wireless network adapter + ++config RTW88_8821CS ++ tristate "Realtek 8821CS SDIO wireless network adapter" ++ depends on MMC ++ select RTW88_CORE ++ select RTW88_SDIO ++ select RTW88_8821C ++ help ++ Select this option will enable support for 8821CS chipset ++ ++ 802.11ac SDIO wireless network adapter ++ ++config RTW88_8821CU ++ tristate "Realtek 8821CU USB wireless network adapter" ++ depends on USB ++ select RTW88_CORE ++ select RTW88_USB ++ select RTW88_8821C ++ help ++ Select this option will enable support for 8821CU chipset ++ ++ 802.11ac USB wireless network adapter ++ + config RTW88_DEBUG + bool "Realtek rtw88 debug support" + depends on RTW88_CORE +diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile +index 73d6807a8cdf..fd212c09d88a 100644 +--- a/drivers/net/wireless/realtek/rtw88/Makefile ++++ b/drivers/net/wireless/realtek/rtw88/Makefile +@@ -15,6 +15,7 @@ rtw88_core-y += main.o \ + ps.o \ + sec.o \ + bf.o \ ++ sar.o \ + regd.o + + rtw88_core-$(CONFIG_PM) += wow.o +@@ -25,23 +26,53 @@ rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o + obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o + rtw88_8822be-objs := rtw8822be.o + ++obj-$(CONFIG_RTW88_8822BS) += rtw88_8822bs.o ++rtw88_8822bs-objs := rtw8822bs.o ++ ++obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o ++rtw88_8822bu-objs := rtw8822bu.o ++ + obj-$(CONFIG_RTW88_8822C) += rtw88_8822c.o + rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o + + obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o + rtw88_8822ce-objs := rtw8822ce.o + ++obj-$(CONFIG_RTW88_8822CS) += rtw88_8822cs.o ++rtw88_8822cs-objs := rtw8822cs.o ++ ++obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o ++rtw88_8822cu-objs := rtw8822cu.o ++ + obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o + rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o + + obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o + rtw88_8723de-objs := rtw8723de.o + ++obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o ++rtw88_8723ds-objs := rtw8723ds.o ++ ++obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o ++rtw88_8723du-objs := rtw8723du.o ++ + obj-$(CONFIG_RTW88_8821C) += rtw88_8821c.o + rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o + + obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o + rtw88_8821ce-objs := rtw8821ce.o + ++obj-$(CONFIG_RTW88_8821CS) += rtw88_8821cs.o ++rtw88_8821cs-objs := rtw8821cs.o ++ ++obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o ++rtw88_8821cu-objs := rtw8821cu.o ++ + obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o + rtw88_pci-objs := pci.o ++ ++obj-$(CONFIG_RTW88_SDIO) += rtw88_sdio.o ++rtw88_sdio-objs := sdio.o ++ ++obj-$(CONFIG_RTW88_USB) += rtw88_usb.o ++rtw88_usb-objs := usb.o +diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c +index aff70e4ae028..95de3d3da065 100644 +--- a/drivers/net/wireless/realtek/rtw88/bf.c ++++ b/drivers/net/wireless/realtek/rtw88/bf.c +@@ -30,11 +30,11 @@ void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct rtw_bfee *bfee = &rtwvif->bfee; + struct rtw_bf_info *bfinfo = &rtwdev->bf_info; +- struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_sta *sta; + struct ieee80211_sta_vht_cap *vht_cap; + struct ieee80211_sta_vht_cap *ic_vht_cap; +@@ -49,25 +49,37 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + + sta = ieee80211_find_sta(vif, bssid); + if (!sta) { ++ rcu_read_unlock(); ++ + rtw_warn(rtwdev, "failed to find station entry for bss %pM\n", + bssid); +- goto out_unlock; ++ return; + } + + ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) + vht_cap = &sta->vht_cap; ++#else ++ vht_cap = &sta->deflink.vht_cap; ++#endif ++ ++ rcu_read_unlock(); + + if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && + (vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { + if (bfinfo->bfer_mu_cnt >= chip->bfer_mu_max_num) { + rtw_dbg(rtwdev, RTW_DBG_BF, "mu bfer number over limit\n"); +- goto out_unlock; ++ return; + } + + ether_addr_copy(bfee->mac_addr, bssid); + bfee->role = RTW_BFEE_MU; + bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ bfee->aid = vif->cfg.aid; ++#else + bfee->aid = bss_conf->aid; ++#endif + bfinfo->bfer_mu_cnt++; + + rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); +@@ -75,7 +87,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) { + rtw_dbg(rtwdev, RTW_DBG_BF, "su bfer number over limit\n"); +- goto out_unlock; ++ return; + } + + sound_dim = vht_cap->cap & +@@ -98,9 +110,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + + rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); + } +- +-out_unlock: +- rcu_read_unlock(); + } + + void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev, +@@ -130,7 +139,8 @@ void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif, + BIT_WMAC_USE_NDPARATE | + (csi_rsc << 13); + +- rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_SOUNDING); ++ rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, ++ RTW_SND_CTRL_SOUNDING); + rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, 0x26); + rtw_write8_clr(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF_REPORT_POLL); + rtw_write8_clr(rtwdev, REG_RXFLTMAP4, BIT_RXFLTMAP4_BF_REPORT_POLL); +@@ -177,7 +187,7 @@ void rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev) + + void rtw_bf_del_sounding(struct rtw_dev *rtwdev) + { +- rtw_write8(rtwdev, REG_SND_PTCL_CTRL, 0); ++ rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 0); + } + + void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif, +@@ -204,7 +214,8 @@ void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif, + } + + /* Sounding protocol control */ +- rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_SOUNDING); ++ rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, ++ RTW_SND_CTRL_SOUNDING); + + /* MAC address/Partial AID of Beamformer */ + for (i = 0; i < ETH_ALEN; i++) +@@ -273,7 +284,8 @@ void rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev, + struct rtw_bf_info *bfinfo = &rtwdev->bf_info; + + rtw_dbg(rtwdev, RTW_DBG_BF, "remove as a su bfee\n"); +- rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_REMOVE); ++ rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, ++ RTW_SND_CTRL_REMOVE); + + switch (bfee->su_reg_index) { + case 0: +@@ -298,7 +310,8 @@ void rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev, + { + struct rtw_bf_info *bfinfo = &rtwdev->bf_info; + +- rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_REMOVE); ++ rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, ++ RTW_SND_CTRL_REMOVE); + + rtw_bf_del_bfer_entry_mu(rtwdev); + +diff --git a/drivers/net/wireless/realtek/rtw88/bf.h b/drivers/net/wireless/realtek/rtw88/bf.h +index 17855edb5006..7b40c2c03856 100644 +--- a/drivers/net/wireless/realtek/rtw88/bf.h ++++ b/drivers/net/wireless/realtek/rtw88/bf.h +@@ -13,6 +13,9 @@ + #define REG_ASSOCIATED_BFMER1_INFO 0x06EC + #define REG_TX_CSI_RPT_PARAM_BW20 0x06F4 + #define REG_SND_PTCL_CTRL 0x0718 ++#define BIT_DIS_CHK_VHTSIGB_CRC BIT(6) ++#define BIT_DIS_CHK_VHTSIGA_CRC BIT(5) ++#define BIT_MASK_BEAMFORM (GENMASK(4, 0) | BIT(7)) + #define REG_MU_TX_CTL 0x14C0 + #define REG_MU_STA_GID_VLD 0x14C4 + #define REG_MU_STA_USER_POS_INFO 0x14C8 +@@ -42,8 +45,8 @@ + #define BIT_RXFLTMAP4_BF_REPORT_POLL BIT(4) + + #define RTW_NDP_RX_STANDBY_TIME 0x70 +-#define RTW_SND_CTRL_REMOVE 0xD8 +-#define RTW_SND_CTRL_SOUNDING 0xDB ++#define RTW_SND_CTRL_REMOVE 0x98 ++#define RTW_SND_CTRL_SOUNDING 0x9B + + enum csi_seg_len { + HAL_CSI_SEG_4K = 0, +diff --git a/drivers/net/wireless/realtek/rtw88/bitfield.h b/drivers/net/wireless/realtek/rtw88/bitfield.h +new file mode 100644 +index 000000000000..230d2383b16d +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/bitfield.h +@@ -0,0 +1,155 @@ ++/* ++ * Copyright (C) 2014 Felix Fietkau ++ * Copyright (C) 2004 - 2009 Ivo van Doorn ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _LINUX_BITFIELD_H ++#define _LINUX_BITFIELD_H ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) ++#include ++#endif ++#include ++ ++/* ++ * Bitfield access macros ++ * ++ * FIELD_{GET,PREP} macros take as first parameter shifted mask ++ * from which they extract the base mask and shift amount. ++ * Mask must be a compilation time constant. ++ * ++ * Example: ++ * ++ * #define REG_FIELD_A GENMASK(6, 0) ++ * #define REG_FIELD_B BIT(7) ++ * #define REG_FIELD_C GENMASK(15, 8) ++ * #define REG_FIELD_D GENMASK(31, 16) ++ * ++ * Get: ++ * a = FIELD_GET(REG_FIELD_A, reg); ++ * b = FIELD_GET(REG_FIELD_B, reg); ++ * ++ * Set: ++ * reg = FIELD_PREP(REG_FIELD_A, 1) | ++ * FIELD_PREP(REG_FIELD_B, 0) | ++ * FIELD_PREP(REG_FIELD_C, c) | ++ * FIELD_PREP(REG_FIELD_D, 0x40); ++ * ++ * Modify: ++ * reg &= ~REG_FIELD_C; ++ * reg |= FIELD_PREP(REG_FIELD_C, c); ++ */ ++ ++#define __bf_shf(x) (__builtin_ffsll(x) - 1) ++ ++#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \ ++ ({ \ ++ BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ ++ _pfx "mask is not constant"); \ ++ BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \ ++ BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ ++ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ ++ _pfx "value too large for the field"); \ ++ BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \ ++ _pfx "type of reg too small for mask"); \ ++ __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ ++ (1ULL << __bf_shf(_mask))); \ ++ }) ++ ++/** ++ * FIELD_FIT() - check if value fits in the field ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to test against the field ++ * ++ * Return: true if @_val can fit inside @_mask, false if @_val is too big. ++ */ ++#define FIELD_FIT(_mask, _val) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \ ++ !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \ ++ }) ++ ++/** ++ * FIELD_PREP() - prepare a bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to put in the field ++ * ++ * FIELD_PREP() masks and shifts up the value. The result should ++ * be combined with other fields of the bitfield using logical OR. ++ */ ++#define FIELD_PREP(_mask, _val) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ ++ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ ++ }) ++ ++/** ++ * FIELD_GET() - extract a bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_reg: value of entire bitfield ++ * ++ * FIELD_GET() extracts the field specified by @_mask from the ++ * bitfield passed in as @_reg by masking and shifting it down. ++ */ ++#define FIELD_GET(_mask, _reg) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \ ++ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ ++ }) ++ ++extern void __compiletime_error("value doesn't fit into mask") ++__field_overflow(void); ++extern void __compiletime_error("bad bitfield mask") ++__bad_mask(void); ++static __always_inline u64 field_multiplier(u64 field) ++{ ++ if ((field | (field - 1)) & ((field | (field - 1)) + 1)) ++ __bad_mask(); ++ return field & -field; ++} ++static __always_inline u64 field_mask(u64 field) ++{ ++ return field / field_multiplier(field); ++} ++#define ____MAKE_OP(type,base,to,from) \ ++static __always_inline __##type type##_encode_bits(base v, base field) \ ++{ \ ++ if (__builtin_constant_p(v) && (v & ~field_mask(field))) \ ++ __field_overflow(); \ ++ return to((v & field_mask(field)) * field_multiplier(field)); \ ++} \ ++static __always_inline __##type type##_replace_bits(__##type old, \ ++ base val, base field) \ ++{ \ ++ return (old & ~to(field)) | type##_encode_bits(val, field); \ ++} \ ++static __always_inline void type##p_replace_bits(__##type *p, \ ++ base val, base field) \ ++{ \ ++ *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ ++} \ ++static __always_inline base type##_get_bits(__##type v, base field) \ ++{ \ ++ return (from(v) & field)/field_multiplier(field); \ ++} ++#define __MAKE_OP(size) \ ++ ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \ ++ ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \ ++ ____MAKE_OP(u##size,u##size,,) ++____MAKE_OP(u8,u8,,) ++__MAKE_OP(16) ++__MAKE_OP(32) ++__MAKE_OP(64) ++#undef __MAKE_OP ++#undef ____MAKE_OP ++ ++#endif +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index aa08fd7d9fcd..86467d2f8888 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -8,11 +8,12 @@ + #include "ps.h" + #include "debug.h" + #include "reg.h" ++#include "phy.h" + + static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, + u8 rssi, u8 rssi_thresh) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 tol = chip->rssi_tolerance; + u8 next_state; + +@@ -35,10 +36,10 @@ static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, + static void rtw_coex_limited_tx(struct rtw_dev *rtwdev, + bool tx_limit_en, bool ampdu_limit_en) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +- bool wifi_under_b_mode = false; ++ u8 num_of_active_port = 1; + + if (!chip->scbd_support) + return; +@@ -70,17 +71,13 @@ static void rtw_coex_limited_tx(struct rtw_dev *rtwdev, + /* set queue life time to avoid can't reach tx retry limit + * if tx is always broken by GNT_BT + */ +- rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); ++ if (num_of_active_port <= 1) ++ rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); + rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808); + + /* auto rate fallback step within 8 retries */ +- if (wifi_under_b_mode) { +- rtw_write32(rtwdev, REG_DARFRC, 0x1000000); +- rtw_write32(rtwdev, REG_DARFRCH, 0x1010101); +- } else { +- rtw_write32(rtwdev, REG_DARFRC, 0x1000000); +- rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); +- } ++ rtw_write32(rtwdev, REG_DARFRC, 0x1000000); ++ rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); + } else { + rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); + rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf); +@@ -101,39 +98,84 @@ static void rtw_coex_limited_wl(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_coex_stat *coex_stat = &coex->stat; + bool tx_limit = false; + bool tx_agg_ctrl = false; + +- if (coex->under_5g || +- coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { +- /* no need to limit tx */ +- } else { ++ if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) { + tx_limit = true; +- if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist || +- coex_stat->bt_hid_pair_num > 0) +- tx_agg_ctrl = true; ++ tx_agg_ctrl = true; + } + + rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl); + } + +-static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) ++static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 bt_rssi; ++ u8 ant_distance = 10; ++ ++ if (coex_stat->bt_disabled) ++ return false; ++ ++ if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy) ++ return false; ++ ++ if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2) ++ return true; ++ ++ /* ant_distance = 5 ~ 40 */ ++ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) && ++ COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) ++ return true; ++ ++ if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) ++ bt_rssi = coex_dm->bt_rssi_state[0]; ++ else ++ bt_rssi = coex_dm->bt_rssi_state[1]; ++ ++ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && ++ COEX_RSSI_HIGH(bt_rssi) && ++ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5) ++ return true; ++ ++ return false; ++} ++ ++static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 para[6] = {0}; + +- if (coex->stop_dm) ++ para[0] = COEX_H2C69_WL_LEAKAP; ++ para[1] = PARA1_H2C69_DIS_5MS; ++ ++ if (enable) ++ para[1] = PARA1_H2C69_EN_5MS; ++ else ++ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; ++ ++ coex_stat->wl_slot_extend = enable; ++ rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); ++} ++ ++static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ ++ if (coex->manual_control || coex->stop_dm) + return; + +- para[0] = COEX_H2C69_WL_LEAKAP; + + if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) { +- para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */ +- rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); +- coex_stat->wl_slot_extend = false; +- coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n"); ++ rtw_coex_wl_slot_extend(rtwdev, false); + return; + } + +@@ -144,16 +186,20 @@ static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) + else + coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], 5ms WL slot extend cnt = %d!!\n", ++ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]); ++ + if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) { +- para[1] = 0x1; /* disable 5ms extend */ +- rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); +- coex_stat->wl_slot_extend = false; +- coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n"); ++ rtw_coex_wl_slot_extend(rtwdev, false); + } + } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) { +- para[1] = 0x0; /* enable 5ms extend */ +- rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); +- coex_stat->wl_slot_extend = true; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n"); ++ ++ rtw_coex_wl_slot_extend(rtwdev, true); + } + } + +@@ -161,11 +207,52 @@ static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_coex_dm *coex_dm = &coex->dm; + +- /* TODO: wait for rx_rate_change_notify implement */ +- coex_stat->wl_cck_lock = false; +- coex_stat->wl_cck_lock_pre = false; +- coex_stat->wl_cck_lock_ever = false; ++ bool is_cck_lock_rate = false; ++ ++ if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT && ++ coex_stat->wl_coex_mode != COEX_WLINK_2GFREE) ++ return; ++ ++ if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE || ++ coex_stat->bt_setup_link) { ++ coex_stat->wl_cck_lock = false; ++ coex_stat->wl_cck_lock_pre = false; ++ return; ++ } ++ ++ if (coex_stat->wl_rx_rate <= COEX_CCK_2 || ++ coex_stat->wl_rts_rx_rate <= COEX_CCK_2) ++ is_cck_lock_rate = true; ++ ++ if (coex_stat->wl_connected && coex_stat->wl_gl_busy && ++ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && ++ (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY || ++ coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY || ++ coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) { ++ if (is_cck_lock_rate) { ++ coex_stat->wl_cck_lock = true; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], cck locking...\n"); ++ ++ } else { ++ coex_stat->wl_cck_lock = false; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], cck unlock...\n"); ++ } ++ } else { ++ coex_stat->wl_cck_lock = false; ++ } ++ ++ /* CCK lock identification */ ++ if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre) ++ ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work, ++ 3 * HZ); ++ ++ coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock; + } + + static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) +@@ -174,11 +261,12 @@ static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 cnt_cck; ++ bool wl_cck_lock = false; + + /* wifi noisy environment identification */ + cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt; + +- if (!coex_stat->wl_gl_busy) { ++ if (!coex_stat->wl_gl_busy && !wl_cck_lock) { + if (cnt_cck > 250) { + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5) + coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++; +@@ -211,6 +299,9 @@ static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) + coex_stat->wl_noisy_level = 1; + else + coex_stat->wl_noisy_level = 0; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n", ++ coex_stat->wl_noisy_level); + } + } + +@@ -219,6 +310,8 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 para[2] = {0}; ++ u8 times; ++ u16 tbtt_interval = coex_stat->wl_beacon_interval; + + if (coex_stat->tdma_timer_base == type) + return; +@@ -227,13 +320,33 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) + + para[0] = COEX_H2C69_TDMA_SLOT; + +- if (type == 3) /* 4-slot */ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n", ++ tbtt_interval); ++ ++ if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) { + para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */ +- else /* 2-slot */ ++ } else if (tbtt_interval < 80 && tbtt_interval > 0) { ++ times = 100 / tbtt_interval; ++ if (100 % tbtt_interval != 0) ++ times++; ++ ++ para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times); ++ } else if (tbtt_interval >= 180) { ++ times = tbtt_interval / 100; ++ if (tbtt_interval % 100 <= 80) ++ times--; ++ ++ para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) | ++ FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1); ++ } else { + para[1] = PARA1_H2C69_TDMA_2SLOT; ++ } + + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n", ++ __func__, para[1]); ++ + /* no 5ms_wl_slot_extend for 4-slot mode */ + if (coex_stat->tdma_timer_base == 3) + rtw_coex_wl_ccklock_action(rtwdev); +@@ -252,7 +365,7 @@ static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap, + + void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u16 val = 0x2; +@@ -287,7 +400,7 @@ EXPORT_SYMBOL(rtw_coex_write_scbd); + + static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->scbd_support) + return 0; +@@ -297,7 +410,7 @@ static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) + + static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; +@@ -307,6 +420,9 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) + + if (coex_rfe->wlg_at_btg && chip->scbd_support && + coex_stat->bt_iqk_state != 0xff) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], (Before Ant Setup) Delay by IQK\n"); ++ + wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY; + do { + /* BT RFK */ +@@ -318,6 +434,10 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) + if (!btk && !wlk) + break; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n", ++ wlk, btk); ++ + mdelay(COEX_MIN_DELAY); + } while (++cnt < wait_cnt); + +@@ -334,12 +454,42 @@ static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) + if (coex_stat->bt_disabled) + return; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ + rtw_fw_query_bt_info(rtwdev); + } + ++static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode) ++{ ++ rtw_coex_set_gnt_fix(rtwdev); ++} ++ ++static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ u32 tmp; ++ ++ tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS); ++ coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp); ++ coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp); ++ ++ tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1); ++ coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp); ++ coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp); ++ ++ rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL, ++ BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n", ++ coex_stat->hi_pri_rx, coex_stat->hi_pri_tx, ++ coex_stat->lo_pri_rx, coex_stat->lo_pri_tx); ++} ++ + static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; +@@ -352,30 +502,32 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) + } + + if (coex_stat->bt_disabled != bt_disabled) { +- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n", ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT state changed (%d) -> (%d)\n", + coex_stat->bt_disabled, bt_disabled); + + coex_stat->bt_disabled = bt_disabled; + coex_stat->bt_ble_scan_type = 0; + coex_dm->cur_bt_lna_lvl = 0; +- } + +- if (!coex_stat->bt_disabled) { +- coex_stat->bt_reenable = true; +- ieee80211_queue_delayed_work(rtwdev->hw, +- &coex->bt_reenable_work, 15 * HZ); +- } else { +- coex_stat->bt_mailbox_reply = false; +- coex_stat->bt_reenable = false; ++ if (!coex_stat->bt_disabled) { ++ coex_stat->bt_reenable = true; ++ ieee80211_queue_delayed_work(rtwdev->hw, ++ &coex->bt_reenable_work, ++ 15 * HZ); ++ } else { ++ coex_stat->bt_mailbox_reply = false; ++ coex_stat->bt_reenable = false; ++ } + } + } + + static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_traffic_stats *stats = &rtwdev->stats; + bool is_5G = false; + bool wl_busy = false; +@@ -420,6 +572,12 @@ static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) + coex_dm->wl_rssi_state[i] = rssi_state; + } + ++ if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || ++ coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); ++ else ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); ++ + switch (reason) { + case COEX_RSN_5GSCANSTART: + case COEX_RSN_5GSWITCHBAND: +@@ -460,8 +618,10 @@ void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb) + struct rtw_coex *coex = &rtwdev->coex; + u8 *payload = get_payload_from_coex_resp(skb); + +- if (payload[0] != COEX_RESP_ACK_BY_WL_FW) ++ if (payload[0] != COEX_RESP_ACK_BY_WL_FW) { ++ dev_kfree_skb_any(skb); + return; ++ } + + skb_queue_tail(&coex->queue, skb); + wake_up(&coex->wait); +@@ -473,7 +633,7 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, + struct rtw_coex *coex = &rtwdev->coex; + struct sk_buff *skb_resp = NULL; + +- mutex_lock(&coex->mutex); ++ lockdep_assert_held(&rtwdev->mutex); + + rtw_fw_query_bt_mp_info(rtwdev, req); + +@@ -490,7 +650,6 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, + } + + out: +- mutex_unlock(&coex->mutex); + return skb_resp; + } + +@@ -499,20 +658,16 @@ static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type) + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; +- bool ret = false; + + req.op_code = BT_MP_INFO_OP_SCAN_TYPE; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) +- goto out; ++ return false; + + payload = get_payload_from_coex_resp(skb); + *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload); + dev_kfree_skb_any(skb); +- ret = true; +- +-out: +- return ret; ++ return true; + } + + static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, +@@ -520,27 +675,40 @@ static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, + { + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; +- bool ret = false; + + req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT; + req.para1 = lna_constrain_level; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) +- goto out; ++ return false; + + dev_kfree_skb_any(skb); +- ret = true; ++ return true; ++} + +-out: +- return ret; ++#define case_BTSTATUS(src) \ ++ case COEX_BTSTATUS_##src: return #src ++ ++static const char *rtw_coex_get_bt_status_string(u8 bt_status) ++{ ++ switch (bt_status) { ++ case_BTSTATUS(NCON_IDLE); ++ case_BTSTATUS(CON_IDLE); ++ case_BTSTATUS(INQ_PAGE); ++ case_BTSTATUS(ACL_BUSY); ++ case_BTSTATUS(SCO_BUSY); ++ case_BTSTATUS(ACL_SCO_BUSY); ++ default: ++ return "Unknown"; ++ } + } + + static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 i; + u8 rssi_state; + u8 rssi_step; +@@ -551,20 +719,11 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) + rssi_state = coex_dm->bt_rssi_state[i]; + rssi_step = chip->bt_rssi_step[i]; + rssi = coex_stat->bt_rssi; +- rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, +- rssi, rssi_step); ++ rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi, ++ rssi_step); + coex_dm->bt_rssi_state[i] = rssi_state; + } + +- for (i = 0; i < COEX_RSSI_STEP; i++) { +- rssi_state = coex_dm->wl_rssi_state[i]; +- rssi_step = chip->wl_rssi_step[i]; +- rssi = rtwdev->dm_info.min_rssi; +- rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, +- rssi, rssi_step); +- coex_dm->wl_rssi_state[i] = rssi_state; +- } +- + if (coex_stat->bt_ble_scan_en && + coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) { + u8 scan_type; +@@ -623,6 +782,7 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) + coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE; + } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { + coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE; ++ coex_stat->bt_multi_link_remain = false; + } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) { + coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE; + } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) || +@@ -639,14 +799,16 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) + + coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++; + +- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__, ++ rtw_coex_get_bt_status_string(coex_dm->bt_status)); + } + + static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) + { +- struct rtw_chip_info *chip = rtwdev->chip; +- struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; + u8 link = 0; + u8 center_chan = 0; + u8 bw; +@@ -657,8 +819,12 @@ static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) + if (type != COEX_MEDIA_DISCONNECT) + center_chan = rtwdev->hal.current_channel; + +- if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) { ++ if (center_chan == 0 || ++ (efuse->share_ant && center_chan <= 14 && ++ coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) { + link = 0; ++ center_chan = 0; ++ bw = 0; + } else if (center_chan <= 14) { + link = 0x1; + +@@ -682,6 +848,9 @@ static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) + coex_dm->wl_ch_info[2] = bw; + + rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link, ++ center_chan, bw); + } + + static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) +@@ -714,6 +883,8 @@ static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl) + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false); + } ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n", ++ __func__, bt_lna_lvl); + } + + static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, +@@ -723,7 +894,7 @@ static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 offset = 0; + +- if (coex->freerun && coex_stat->wl_noisy_level <= 1) ++ if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5) + offset = 3; + + rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl); +@@ -761,15 +932,17 @@ EXPORT_SYMBOL(rtw_coex_write_indirect_reg); + + static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_hw_reg *btg_reg = chip->btg_reg; + + if (wifi_control) { +- rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); ++ rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3, ++ BIT_LTE_MUX_CTRL_PATH >> 24); + if (btg_reg) + rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask); + } else { +- rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); ++ rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3, ++ BIT_LTE_MUX_CTRL_PATH >> 24); + if (btg_reg) + rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask); + } +@@ -777,52 +950,151 @@ static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) + + static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) + { +- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state); +- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state); + } + + static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) + { +- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state); +- rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state); ++} ++ ++static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state) ++{ ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; ++ ++ if (!force && state == coex_stat->wl_mimo_ps) ++ return; ++ ++ coex_stat->wl_mimo_ps = state; ++ ++ rtw_set_txrx_1ss(rtwdev, state); ++ ++ rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): state = %d\n", __func__, state); + } + +-static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1) ++static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force, ++ u8 table_case) + { +-#define DEF_BRK_TABLE_VAL 0xf0ffffff ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 h2c_para[6] = {0}; ++ u32 table_wl = 0x5a5a5a5a; ++ ++ h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A; ++ /* no definition */ ++ h2c_para[1] = 0x1; ++ ++ if (efuse->share_ant) { ++ if (table_case < chip->table_sant_num) ++ table_wl = chip->table_sant[table_case].wl; ++ } else { ++ if (table_case < chip->table_nsant_num) ++ table_wl = chip->table_nsant[table_case].wl; ++ } ++ ++ /* tell WL FW WL slot toggle table-A*/ ++ h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0)); ++ h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8)); ++ h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16)); ++ h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24)); ++ ++ rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n", ++ __func__, h2c_para[0], h2c_para[1], h2c_para[2], ++ h2c_para[3], h2c_para[4], h2c_para[5]); ++} ++ ++#define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa ++static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force, ++ u8 interval, u32 table) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ u8 cur_h2c_para[6] = {0}; ++ u8 i; ++ ++ cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B; ++ cur_h2c_para[1] = interval; ++ cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0)); ++ cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8)); ++ cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16)); ++ cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24)); ++ ++ coex_stat->wl_toggle_interval = interval; ++ ++ for (i = 0; i <= 5; i++) ++ coex_stat->wl_toggle_para[i] = cur_h2c_para[i]; ++ ++ rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n", ++ __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2], ++ cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]); ++} ++ ++static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0, ++ u32 table1) ++{ ++#define DEF_BRK_TABLE_VAL 0xf0ffffff ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ ++ /* If last tdma is wl slot toggle, force write table*/ ++ if (!force && coex_dm->reason != COEX_RSN_LPS) { ++ if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) && ++ table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1)) ++ return; ++ } + rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0); + rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1); + rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0, ++ table1); + } + +-static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type) ++static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw_coex_stat *coex_stat = &coex->stat; + + coex_dm->cur_table = type; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type); ++ + if (efuse->share_ant) { + if (type < chip->table_sant_num) +- rtw_coex_set_table(rtwdev, ++ rtw_coex_set_table(rtwdev, force, + chip->table_sant[type].bt, + chip->table_sant[type].wl); + } else { + type = type - 100; + if (type < chip->table_nsant_num) +- rtw_coex_set_table(rtwdev, ++ rtw_coex_set_table(rtwdev, force, + chip->table_nsant[type].bt, + chip->table_nsant[type].wl); + } ++ if (coex_stat->wl_slot_toggle_change) ++ rtw_btc_wltoggle_table_a(rtwdev, true, type); + } + + static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable) + { + struct rtw_coex *coex = &rtwdev->coex; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + + rtw_fw_bt_ignore_wlan_action(rtwdev, enable); +@@ -841,15 +1113,18 @@ static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, + case COEX_PS_WIFI_NATIVE: + /* recover to original 32k low power setting */ + coex_stat->wl_force_lps_ctrl = false; +- ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__); + rtw_leave_lps(rtwdev); + break; + case COEX_PS_LPS_OFF: + coex_stat->wl_force_lps_ctrl = true; + if (lps_mode) +- rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0); ++ rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0); + + rtw_leave_lps(rtwdev); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__); + break; + default: + break; +@@ -859,13 +1134,17 @@ static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, + static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, + u8 byte3, u8 byte4, u8 byte5) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex_stat *coex_stat = &coex->stat; + u8 ps_type = COEX_PS_WIFI_NATIVE; + bool ap_enable = false; + + if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n", ++ __func__); ++ + byte1 &= ~BIT(4); + byte1 |= BIT(5); + +@@ -874,13 +1153,22 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, + + ps_type = COEX_PS_WIFI_NATIVE; + rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); +- } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) { ++ } else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) || ++ coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__, ++ byte1); ++ + if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) + ps_type = COEX_PS_LPS_OFF; + else + ps_type = COEX_PS_LPS_ON; + rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); + } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): native power save (byte1 = 0x%x)\n", ++ __func__, byte1); ++ + ps_type = COEX_PS_WIFI_NATIVE; + rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); + } +@@ -892,39 +1180,45 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, + coex_dm->ps_tdma_para[4] = byte5; + + rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); ++ ++ if (byte1 & BIT(2)) { ++ coex_stat->wl_slot_toggle = true; ++ coex_stat->wl_slot_toggle_change = false; ++ } else { ++ coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle; ++ coex_stat->wl_slot_toggle = false; ++ } + } + + static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_coex_stat *coex_stat = &coex->stat; +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 n, type; + bool turn_on; + bool wl_busy = false; + +- if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */ +- rtw_coex_tdma_timer_base(rtwdev, 3); ++ if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */ ++ rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT); + else +- rtw_coex_tdma_timer_base(rtwdev, 0); ++ rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT); + + type = (u8)(tcase & 0xff); + + turn_on = (type == 0 || type == 100) ? false : true; + +- if (!force) { +- if (turn_on == coex_dm->cur_ps_tdma_on && +- type == coex_dm->cur_ps_tdma) { +- return; +- } +- } +- +- /* enable TBTT interrupt */ +- if (turn_on) +- rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); ++ if (!force && turn_on == coex_dm->cur_ps_tdma_on && ++ type == coex_dm->cur_ps_tdma) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n", ++ (coex_dm->cur_ps_tdma_on ? "on" : "off"), ++ coex_dm->cur_ps_tdma); + ++ return; ++ } + wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); + + if ((coex_stat->bt_a2dp_exist && +@@ -934,6 +1228,10 @@ static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) + else + rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); + ++ /* update pre state */ ++ coex_dm->cur_ps_tdma_on = turn_on; ++ coex_dm->cur_ps_tdma = type; ++ + if (efuse->share_ant) { + if (type < chip->tdma_sant_num) + rtw_coex_set_tdma(rtwdev, +@@ -953,17 +1251,16 @@ static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) + chip->tdma_nsant[n].para[4]); + } + +- /* update pre state */ +- coex_dm->cur_ps_tdma_on = turn_on; +- coex_dm->cur_ps_tdma = type; + +- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n", ++ turn_on ? "on" : "off", type); + } + + static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_coex_rfe *coex_rfe = &coex->rfe; + struct rtw_coex_dm *coex_dm = &coex->dm; + u8 ctrl_type = COEX_SWITCH_CTRL_MAX; + u8 pos_type = COEX_SWITCH_TO_MAX; +@@ -976,8 +1273,14 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + /* avoid switch coex_ctrl_owner during BT IQK */ + rtw_coex_check_rfk(rtwdev); + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], coex_stat->bt_disabled = 0x%x\n", ++ coex_stat->bt_disabled); ++ + switch (phase) { + case COEX_SET_ANT_POWERON: ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__); + /* set path control owner to BT at power-on */ + if (coex_stat->bt_disabled) + rtw_coex_coex_ctrl_owner(rtwdev, true); +@@ -988,6 +1291,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_BT; + break; + case COEX_SET_ANT_INIT: ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__); + if (coex_stat->bt_disabled) { + /* set GNT_BT to SW low */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); +@@ -1009,10 +1314,12 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_BT; + break; + case COEX_SET_ANT_WONLY: ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__); + /* set GNT_BT to SW Low */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); + +- /* Set GNT_WL to SW high */ ++ /* set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set path control owner to wl at initial step */ +@@ -1022,6 +1329,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_WLG; + break; + case COEX_SET_ANT_WOFF: ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__); + /* set path control owner to BT */ + rtw_coex_coex_ctrl_owner(rtwdev, false); + +@@ -1029,6 +1338,8 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_NOCARE; + break; + case COEX_SET_ANT_2G: ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__); + /* set GNT_BT to PTA */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + +@@ -1042,8 +1353,11 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_NOCARE; + break; + case COEX_SET_ANT_5G: +- /* set GNT_BT to PTA */ +- rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__); ++ ++ /* set GNT_BT to HW PTA */ ++ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + + /* set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); +@@ -1055,8 +1369,11 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_WLA; + break; + case COEX_SET_ANT_2G_FREERUN: +- /* set GNT_BT to SW high */ +- rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__); ++ ++ /* set GNT_BT to HW PTA */ ++ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + + /* Set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); +@@ -1068,10 +1385,12 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + pos_type = COEX_SWITCH_TO_WLG_BT; + break; + case COEX_SET_ANT_2G_WLBT: +- /* set GNT_BT to SW high */ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__); ++ /* set GNT_BT to HW PTA */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + +- /* Set GNT_WL to SW high */ ++ /* Set GNT_WL to HW PTA */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); + + /* set path control owner to wl at runtime step */ +@@ -1085,10 +1404,58 @@ static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) + return; + } + +- if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX) ++ if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX && ++ coex_rfe->ant_switch_exist) + rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); + } + ++#define case_ALGO(src) \ ++ case COEX_ALGO_##src: return #src ++ ++static const char *rtw_coex_get_algo_string(u8 algo) ++{ ++ switch (algo) { ++ case_ALGO(NOPROFILE); ++ case_ALGO(HFP); ++ case_ALGO(HID); ++ case_ALGO(A2DP); ++ case_ALGO(PAN); ++ case_ALGO(A2DP_HID); ++ case_ALGO(A2DP_PAN); ++ case_ALGO(PAN_HID); ++ case_ALGO(A2DP_PAN_HID); ++ default: ++ return "Unknown"; ++ } ++} ++ ++#define case_BT_PROFILE(src) \ ++ case BPM_##src: return #src ++ ++static const char *rtw_coex_get_bt_profile_string(u8 bt_profile) ++{ ++ switch (bt_profile) { ++ case_BT_PROFILE(NOPROFILE); ++ case_BT_PROFILE(HFP); ++ case_BT_PROFILE(HID); ++ case_BT_PROFILE(A2DP); ++ case_BT_PROFILE(PAN); ++ case_BT_PROFILE(HID_HFP); ++ case_BT_PROFILE(A2DP_HFP); ++ case_BT_PROFILE(A2DP_HID); ++ case_BT_PROFILE(A2DP_HID_HFP); ++ case_BT_PROFILE(PAN_HFP); ++ case_BT_PROFILE(PAN_HID); ++ case_BT_PROFILE(PAN_HID_HFP); ++ case_BT_PROFILE(PAN_A2DP); ++ case_BT_PROFILE(PAN_A2DP_HFP); ++ case_BT_PROFILE(PAN_A2DP_HID); ++ case_BT_PROFILE(PAN_A2DP_HID_HFP); ++ default: ++ return "Unknown"; ++ } ++} ++ + static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; +@@ -1149,15 +1516,22 @@ static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) + break; + } + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT Profile = %s => Algorithm = %s\n", ++ rtw_coex_get_bt_profile_string(profile_map), ++ rtw_coex_get_algo_string(algorithm)); + return algorithm; + } + + static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 2; +@@ -1168,26 +1542,28 @@ static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) + tdma_case = 100; + } + +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 level = 0; ++ bool bt_afh_loss = true; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + + if (efuse->share_ant) + return; + + coex->freerun = true; + +- if (coex_stat->wl_connected) ++ if (bt_afh_loss) + rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); +@@ -1211,41 +1587,49 @@ static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) + else + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); + +- rtw_coex_table(rtwdev, 100); ++ rtw_coex_table(rtwdev, false, 100); + rtw_coex_tdma(rtwdev, false, 100); + } + +-static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) ++static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ +- table_case = 2; +- tdma_case = 0; ++ table_case = 9; ++ tdma_case = 16; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + +-static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) ++static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ +- table_case = 1; ++ table_case = 2; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ +@@ -1253,26 +1637,68 @@ static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) + tdma_case = 100; + } + ++ rtw_coex_table(rtwdev, false, table_case); ++ rtw_coex_tdma(rtwdev, false, tdma_case); ++} ++ ++static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 table_case, tdma_case; ++ u32 slot_type = 0; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); +- rtw_coex_tdma(rtwdev, false, tdma_case); ++ ++ if (efuse->share_ant) { /* Shared-Ant */ ++ if (coex_stat->wl_gl_busy) { ++ table_case = 26; ++ if (coex_stat->bt_hid_exist && ++ coex_stat->bt_profile_num == 1) { ++ slot_type = TDMA_4SLOT; ++ tdma_case = 20; ++ } else { ++ tdma_case = 20; ++ } ++ } else { ++ table_case = 1; ++ tdma_case = 0; ++ } ++ } else { /* Non-Shared-Ant */ ++ if (coex_stat->wl_gl_busy) ++ table_case = 115; ++ else ++ table_case = 100; ++ tdma_case = 100; ++ } ++ ++ rtw_coex_table(rtwdev, false, table_case); ++ rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + + static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + u8 table_case = 0xff, tdma_case = 0xff; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (coex_rfe->ant_switch_with_bt && + coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + if (efuse->share_ant && +- COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) { ++ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && ++ coex_stat->wl_gl_busy) { + table_case = 0; + tdma_case = 0; + } else if (!efuse->share_ant) { +@@ -1283,9 +1709,7 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) + + if (table_case != 0xff && tdma_case != 0xff) { + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); +- rtw_coex_table(rtwdev, table_case); +- rtw_coex_tdma(rtwdev, false, tdma_case); +- return; ++ goto exit; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +@@ -1296,8 +1720,12 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) + table_case = 10; + tdma_case = 3; + } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { +- table_case = 6; +- tdma_case = 7; ++ table_case = 11; ++ ++ if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250) ++ tdma_case = 17; ++ else ++ tdma_case = 7; + } else { + table_case = 12; + tdma_case = 7; +@@ -1308,7 +1736,7 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) + table_case = 112; + tdma_case = 104; + } else if ((coex_stat->bt_ble_scan_type & 0x2) && +- coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { ++ coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + table_case = 114; + tdma_case = 103; + } else { +@@ -1317,21 +1745,25 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) + } + } + +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++exit: ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + bool wl_hi_pri = false; + u8 table_case, tdma_case; + u32 slot_type = 0; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || + coex_stat->wl_hi_pri_task2) + wl_hi_pri = true; +@@ -1339,7 +1771,10 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) + if (efuse->share_ant) { + /* Shared-Ant */ + if (wl_hi_pri) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi hi-pri task\n"); + table_case = 15; ++ + if (coex_stat->bt_profile_num > 0) + tdma_case = 10; + else if (coex_stat->wl_hi_pri_task1) +@@ -1349,6 +1784,8 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) + else + tdma_case = 9; + } else if (coex_stat->wl_gl_busy) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi busy\n"); + if (coex_stat->bt_profile_num == 0) { + table_case = 12; + tdma_case = 18; +@@ -1363,63 +1800,120 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) + tdma_case = 26; + } + } else if (coex_stat->wl_connected) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi connected\n"); + table_case = 9; + tdma_case = 27; + } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi not-connected\n"); + table_case = 1; + tdma_case = 0; + } + } else { + /* Non_Shared-Ant */ + if (wl_hi_pri) { +- table_case = 113; +- if (coex_stat->bt_a2dp_exist && +- !coex_stat->bt_pan_exist) +- tdma_case = 111; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi hi-pri task\n"); ++ table_case = 114; ++ ++ if (coex_stat->bt_profile_num > 0) ++ tdma_case = 110; + else if (coex_stat->wl_hi_pri_task1) + tdma_case = 106; + else if (!coex_stat->bt_page) + tdma_case = 108; + else + tdma_case = 109; +- } else if (coex_stat->wl_gl_busy) { ++ } else if (coex_stat->wl_gl_busy) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi busy\n"); + table_case = 114; + tdma_case = 121; + } else if (coex_stat->wl_connected) { +- table_case = 100; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi connected\n"); ++ table_case = 101; + tdma_case = 100; + } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt inq/page + wifi not-connected\n"); + table_case = 101; + tdma_case = 100; + } + } + +- rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n", ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n", + wl_hi_pri, coex_stat->bt_page); + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + ++static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ u8 table_case, tdma_case; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ ++ if (efuse->share_ant) { ++ coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; ++ if (coex_stat->bt_whck_test) ++ table_case = 2; ++ else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist) ++ table_case = 33; ++ else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page) ++ table_case = 0; ++ else if (coex_stat->bt_a2dp_exist) ++ table_case = 34; ++ else ++ table_case = 33; ++ ++ tdma_case = 0; ++ } else { ++ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) ++ tdma_case = 112; ++ else ++ tdma_case = 113; ++ ++ table_case = 121; ++ } ++ ++ if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { ++ if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]); ++ else ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]); ++ } else { ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ } ++ ++ rtw_coex_table(rtwdev, false, table_case); ++ rtw_coex_tdma(rtwdev, false, tdma_case); ++} ++ + static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ +- if (coex_stat->bt_multi_link) { +- table_case = 10; +- tdma_case = 17; +- } else { +- table_case = 10; +- tdma_case = 5; +- } ++ table_case = 10; ++ tdma_case = 5; + } else { + /* Non-Shared-Ant */ + if (coex_stat->bt_multi_link) { +@@ -1431,100 +1925,121 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) + } + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; +- u32 wl_bw; ++ u32 slot_type = 0; ++ bool bt_multi_link_remain = false, is_toggle_table = false; + +- wl_bw = rtwdev->hal.current_band_width; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->bt_ble_exist) { + /* RCU */ +- if (!coex_stat->wl_gl_busy) +- table_case = 14; +- else +- table_case = 15; +- +- if (coex_stat->bt_a2dp_active || wl_bw == 0) +- tdma_case = 18; +- else if (coex_stat->wl_gl_busy) +- tdma_case = 8; +- else +- tdma_case = 4; ++ if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) { ++ table_case = 26; ++ tdma_case = 2; ++ } else { ++ table_case = 27; ++ tdma_case = 9; ++ } + } else { +- if (coex_stat->bt_a2dp_active || wl_bw == 0) { +- table_case = 8; +- tdma_case = 4; ++ /* Legacy HID */ ++ if (coex_stat->bt_profile_num == 1 && ++ (coex_stat->bt_multi_link || ++ (coex_stat->lo_pri_rx + ++ coex_stat->lo_pri_tx > 360) || ++ coex_stat->bt_slave || ++ bt_multi_link_remain)) { ++ slot_type = TDMA_4SLOT; ++ table_case = 12; ++ tdma_case = 20; ++ } else if (coex_stat->bt_a2dp_active) { ++ table_case = 9; ++ tdma_case = 18; ++ } else if (coex_stat->bt_418_hid_exist && ++ coex_stat->wl_gl_busy) { ++ is_toggle_table = true; ++ slot_type = TDMA_4SLOT; ++ table_case = 9; ++ tdma_case = 24; ++ } else if (coex_stat->bt_ble_hid_exist && ++ coex_stat->wl_gl_busy) { ++ table_case = 32; ++ tdma_case = 9; + } else { +- /* for 4/18 HID */ +- if (coex_stat->bt_418_hid_exist && +- coex_stat->wl_gl_busy) +- table_case = 12; +- else +- table_case = 10; +- tdma_case = 4; ++ table_case = 9; ++ tdma_case = 9; + } + } + } else { + /* Non-Shared-Ant */ +- if (coex_stat->bt_a2dp_active) { +- table_case = 113; +- tdma_case = 118; +- } else if (coex_stat->bt_ble_exist) { ++ if (coex_stat->bt_ble_exist) { + /* BLE */ ++ if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) { ++ table_case = 121; ++ tdma_case = 102; ++ } else { ++ table_case = 122; ++ tdma_case = 109; ++ } ++ } else if (coex_stat->bt_a2dp_active) { + table_case = 113; +- +- if (coex_stat->wl_gl_busy) +- tdma_case = 106; +- else +- tdma_case = 104; ++ tdma_case = 118; + } else { + table_case = 113; + tdma_case = 104; + } + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); +- rtw_coex_tdma(rtwdev, false, tdma_case); ++ rtw_coex_table(rtwdev, false, table_case); ++ if (is_toggle_table) { ++ rtw_btc_wltoggle_table_a(rtwdev, true, table_case); ++ rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE); ++ } ++ ++ rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + + static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + u32 slot_type = 0; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ ++ slot_type = TDMA_4SLOT; ++ + if (efuse->share_ant) { + /* Shared-Ant */ +- slot_type = TDMA_4SLOT; +- + if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) +- table_case = 10; ++ table_case = 12; + else + table_case = 9; + +- if (coex_stat->wl_gl_busy) +- tdma_case = 13; +- else ++ if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) + tdma_case = 14; ++ else ++ tdma_case = 13; + } else { + /* Non-Shared-Ant */ + table_case = 112; +@@ -1535,21 +2050,24 @@ static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) + tdma_case = 113; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + + static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + bool ap_enable = false; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { /* Shared-Ant */ + if (ap_enable) { + table_case = 2; +@@ -1571,20 +2089,22 @@ static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) + } + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) +@@ -1595,7 +2115,7 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) + if (coex_stat->wl_gl_busy) + tdma_case = 17; + else +- tdma_case = 19; ++ tdma_case = 20; + } else { + /* Non-Shared-Ant */ + table_case = 112; +@@ -1606,35 +2126,45 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) + tdma_case = 119; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; +- u8 table_case, tdma_case; ++ u8 table_case, tdma_case, interval = 0; + u32 slot_type = 0; ++ bool is_toggle_table = false; ++ ++ slot_type = TDMA_4SLOT; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + + if (efuse->share_ant) { + /* Shared-Ant */ +- slot_type = TDMA_4SLOT; +- +- if (coex_stat->bt_ble_exist) +- table_case = 26; +- else ++ if (coex_stat->bt_ble_exist) { ++ table_case = 26; /* for RCU */ ++ } else if (coex_stat->bt_418_hid_exist) { + table_case = 9; +- +- if (coex_stat->wl_gl_busy) { +- tdma_case = 13; ++ interval = 1; + } else { ++ table_case = 9; ++ } ++ ++ if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) { + tdma_case = 14; ++ } else if (coex_stat->bt_418_hid_exist) { ++ is_toggle_table = true; ++ tdma_case = 23; ++ } else { ++ tdma_case = 13; + } + } else { + /* Non-Shared-Ant */ +@@ -1649,32 +2179,52 @@ static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) + tdma_case = 113; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); ++ if (is_toggle_table) { ++ rtw_btc_wltoggle_table_a(rtwdev, true, table_case); ++ rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE); ++ } + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + + static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; ++ bool wl_cpt_test = false, bt_cpt_test = false; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + if (efuse->share_ant) { + /* Shared-Ant */ +- if (coex_stat->wl_gl_busy && +- coex_stat->wl_noisy_level == 0) +- table_case = 14; +- else +- table_case = 10; ++ if (wl_cpt_test) { ++ if (coex_stat->wl_gl_busy) { ++ table_case = 20; ++ tdma_case = 17; ++ } else { ++ table_case = 10; ++ tdma_case = 15; ++ } ++ } else if (bt_cpt_test) { ++ table_case = 26; ++ tdma_case = 26; ++ } else { ++ if (coex_stat->wl_gl_busy && ++ coex_stat->wl_noisy_level == 0) ++ table_case = 14; ++ else ++ table_case = 10; + +- if (coex_stat->wl_gl_busy) +- tdma_case = 15; +- else +- tdma_case = 20; ++ if (coex_stat->wl_gl_busy) ++ tdma_case = 15; ++ else ++ tdma_case = 20; ++ } + } else { + /* Non-Shared-Ant */ + table_case = 112; +@@ -1685,20 +2235,28 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) + tdma_case = 120; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ if (wl_cpt_test) ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]); ++ else ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 9; +@@ -1717,20 +2275,22 @@ static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) + tdma_case = 119; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 10; +@@ -1749,20 +2309,28 @@ static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) + tdma_case = 120; + } + +- rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex *coex = &rtwdev->coex; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex_stat *coex_stat = &coex->stat; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); + ++ if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc) ++ coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 0; +@@ -1773,18 +2341,20 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) + tdma_case = 100; + } + +- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 2; +@@ -1795,22 +2365,25 @@ static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) + tdma_case = 100; + } + +- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex_stat *coex_stat = &coex->stat; + u8 table_case, tdma_case; + + if (coex->under_5g) + return; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 28; +@@ -1821,34 +2394,48 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) + tdma_case = 100; + } + +- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ if (coex_stat->bt_game_hid_exist) { ++ coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; ++ if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]); ++ else ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]); ++ } else { ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ } ++ ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + + static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + u32 slot_type = 0; + +- if (efuse->share_ant) { +- /* Shared-Ant */ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ ++ if (efuse->share_ant) { /* Shared-Ant */ + if (coex_stat->bt_a2dp_exist) { + slot_type = TDMA_4SLOT; +- table_case = 9; + tdma_case = 11; ++ if (coex_stat->wl_gl_busy) ++ table_case = 26; ++ else ++ table_case = 9; + } else { + table_case = 9; + tdma_case = 7; + } +- } else { +- /* Non-Shared-Ant */ ++ } else { /* Non-Shared-Ant */ + if (coex_stat->bt_a2dp_exist) { ++ slot_type = TDMA_4SLOT; + table_case = 112; + tdma_case = 111; + } else { +@@ -1857,18 +2444,20 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) + } + } + +- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); + } + + static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; +- struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); ++ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); ++ + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 1; +@@ -1879,9 +2468,7 @@ static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) + tdma_case = 100; + } + +- rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- rtw_coex_table(rtwdev, table_case); ++ rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } + +@@ -1889,17 +2476,9 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +- struct rtw_coex_dm *coex_dm = &coex->dm; +- struct rtw_efuse *efuse = &rtwdev->efuse; + u8 algorithm; + +- /* Non-Shared-Ant */ +- if (!efuse->share_ant && coex_stat->wl_gl_busy && +- COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && +- COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) { +- rtw_coex_action_freerun(rtwdev); +- return; +- } ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + + algorithm = rtw_coex_algorithm(rtwdev); + +@@ -1908,10 +2487,15 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) + rtw_coex_action_bt_hfp(rtwdev); + break; + case COEX_ALGO_HID: +- rtw_coex_action_bt_hid(rtwdev); ++ if (rtw_coex_freerun_check(rtwdev)) ++ rtw_coex_action_freerun(rtwdev); ++ else ++ rtw_coex_action_bt_hid(rtwdev); + break; + case COEX_ALGO_A2DP: +- if (coex_stat->bt_a2dp_sink) ++ if (rtw_coex_freerun_check(rtwdev)) ++ rtw_coex_action_freerun(rtwdev); ++ else if (coex_stat->bt_a2dp_sink) + rtw_coex_action_bt_a2dpsink(rtwdev); + else + rtw_coex_action_bt_a2dp(rtwdev); +@@ -1920,7 +2504,10 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) + rtw_coex_action_bt_pan(rtwdev); + break; + case COEX_ALGO_A2DP_HID: +- rtw_coex_action_bt_a2dp_hid(rtwdev); ++ if (rtw_coex_freerun_check(rtwdev)) ++ rtw_coex_action_freerun(rtwdev); ++ else ++ rtw_coex_action_bt_a2dp_hid(rtwdev); + break; + case COEX_ALGO_A2DP_PAN: + rtw_coex_action_bt_a2dp_pan(rtwdev); +@@ -1940,9 +2527,11 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) + + static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_coex_stat *coex_stat = &coex->stat; ++ bool rf4ce_en = false; + + lockdep_assert_held(&rtwdev->mutex); + +@@ -1951,20 +2540,38 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) + + coex_dm->reason = reason; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__, ++ reason); ++ + /* update wifi_link_info_ext variable */ + rtw_coex_update_wl_link_info(rtwdev, reason); + + rtw_coex_monitor_bt_enable(rtwdev); + +- if (coex->stop_dm) ++ if (coex->manual_control) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], return for Manual CTRL!!\n"); ++ return; ++ } ++ ++ if (coex->stop_dm) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], return for Stop Coex DM!!\n"); + return; ++ } + +- if (coex_stat->wl_under_ips) ++ if (coex_stat->wl_under_ips) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], return for wifi is under IPS!!\n"); + return; ++ } + + if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO && +- !coex_stat->bt_setup_link) ++ !coex_stat->bt_setup_link) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], return for coex_freeze!!\n"); + return; ++ } + + coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++; + coex->freerun = false; +@@ -1976,10 +2583,16 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) + goto exit; + } + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n"); + coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT; +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); ++ + if (coex_stat->bt_disabled) { +- rtw_coex_action_wl_only(rtwdev); ++ if (coex_stat->wl_connected && rf4ce_en) ++ rtw_coex_action_rf4ce(rtwdev); ++ else if (!coex_stat->wl_connected) ++ rtw_coex_action_wl_not_connected(rtwdev); ++ else ++ rtw_coex_action_wl_only(rtwdev); + goto exit; + } + +@@ -1988,6 +2601,11 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) + goto exit; + } + ++ if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) { ++ rtw_coex_action_bt_game_hid(rtwdev); ++ goto exit; ++ } ++ + if (coex_stat->bt_whck_test) { + rtw_coex_action_bt_whql_test(rtwdev); + goto exit; +@@ -2010,18 +2628,33 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) + goto exit; + } + +- if (coex_stat->wl_linkscan_proc) { ++ if (coex_stat->wl_linkscan_proc && !coex->freerun) { + rtw_coex_action_wl_linkscan(rtwdev); + goto exit; + } + +- if (coex_stat->wl_connected) ++ if (coex_stat->wl_connected) { + rtw_coex_action_wl_connected(rtwdev); +- else ++ goto exit; ++ } else { + rtw_coex_action_wl_not_connected(rtwdev); ++ goto exit; ++ } + + exit: +- rtw_coex_set_gnt_fix(rtwdev); ++ ++ if (chip->wl_mimo_ps_support) { ++ if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { ++ if (coex_dm->reason == COEX_RSN_2GMEDIA) ++ rtw_coex_mimo_ps(rtwdev, true, true); ++ else ++ rtw_coex_mimo_ps(rtwdev, false, true); ++ } else { ++ rtw_coex_mimo_ps(rtwdev, false, false); ++ } ++ } ++ ++ rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode); + rtw_coex_limited_wl(rtwdev); + } + +@@ -2048,14 +2681,26 @@ static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev) + coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW; + + coex_stat->wl_coex_mode = COEX_WLINK_MAX; ++ coex_stat->wl_rx_rate = DESC_RATE5_5M; ++ coex_stat->wl_rts_rx_rate = DESC_RATE5_5M; + } + + static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) + { + struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + + rtw_coex_init_coex_var(rtwdev); ++ ++ coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4)); ++ + rtw_coex_monitor_bt_enable(rtwdev); ++ rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend); ++ ++ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); ++ + rtw_coex_set_rfe_type(rtwdev); + rtw_coex_set_init(rtwdev); + +@@ -2073,21 +2718,24 @@ static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); + coex->stop_dm = true; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n", ++ __func__); + } else if (wifi_only) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY); +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, + true); + coex->stop_dm = true; + } else { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT); +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, + true); + coex->stop_dm = false; + coex->freeze = true; + } + + /* PTA parameter */ +- rtw_coex_table(rtwdev, 0); ++ rtw_coex_table(rtwdev, true, 1); + rtw_coex_tdma(rtwdev, true, 0); + rtw_coex_query_bt_info(rtwdev); + } +@@ -2095,12 +2743,16 @@ static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) + void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) + { + struct rtw_coex *coex = &rtwdev->coex; ++ u8 table_case = 1; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + + coex->stop_dm = true; + coex->wl_rf_off = false; + + /* enable BB, we can write 0x948 */ +- rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1)); ++ rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, ++ BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB); + + rtw_coex_monitor_bt_enable(rtwdev); + rtw_coex_set_rfe_type(rtwdev); +@@ -2108,8 +2760,15 @@ void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) + /* set antenna path to BT */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON); + ++ rtw_coex_table(rtwdev, true, table_case); + /* red x issue */ + rtw_write8(rtwdev, 0xff1a, 0x0); ++ rtw_coex_set_gnt_debug(rtwdev); ++} ++ ++void rtw_coex_power_off_setting(struct rtw_dev *rtwdev) ++{ ++ rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN); + } + + void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) +@@ -2122,10 +2781,12 @@ void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + + if (type == COEX_IPS_ENTER) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n"); ++ + coex_stat->wl_under_ips = true; + + /* for lps off */ +@@ -2134,11 +2795,11 @@ void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); + rtw_coex_action_coex_all_off(rtwdev); + } else if (type == COEX_IPS_LEAVE) { +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n"); + ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); + /* run init hw config (exclude wifi only) */ + __rtw_coex_init_hw_config(rtwdev, false); +- /* sw all off */ + + coex_stat->wl_under_ips = false; + } +@@ -2149,10 +2810,12 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + + if (type == COEX_LPS_ENABLE) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n"); ++ + coex_stat->wl_under_lps = true; + + if (coex_stat->wl_force_lps_ctrl) { +@@ -2161,10 +2824,13 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) + } else { + /* for native ps */ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false); + + rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); + } + } else if (type == COEX_LPS_DISABLE) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n"); ++ + coex_stat->wl_under_lps = false; + + /* for lps off */ +@@ -2172,6 +2838,8 @@ void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) + + if (!coex_stat->wl_force_lps_ctrl) + rtw_coex_query_bt_info(rtwdev); ++ ++ rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); + } + } + +@@ -2180,25 +2848,34 @@ void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type) + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + + coex->freeze = false; +- +- if (type != COEX_SCAN_FINISH) +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | +- COEX_SCBD_ONOFF, true); ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); + + if (type == COEX_SCAN_START_5G) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], SCAN START notify (5G)\n"); ++ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART); + } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], SCAN START notify (2G)\n"); ++ + coex_stat->wl_hi_pri_task2 = true; + + /* Force antenna setup for no scan result issue */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART); + } else { ++ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */ ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n", ++ coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]); ++ + coex_stat->wl_hi_pri_task2 = false; + rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH); + } +@@ -2208,9 +2885,20 @@ void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type) + { + struct rtw_coex *coex = &rtwdev->coex; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + ++ if (type == COEX_SWITCH_TO_5G) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n", ++ __func__); ++ } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__); ++ } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n", ++ __func__); ++ } ++ + if (type == COEX_SWITCH_TO_5G) + rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND); + else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) +@@ -2224,22 +2912,33 @@ void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | +- COEX_SCBD_ONOFF, true); ++ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); + + if (type == COEX_ASSOCIATE_5G_START) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n", ++ __func__); ++ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART); + } else if (type == COEX_ASSOCIATE_5G_FINISH) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n", ++ __func__); ++ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH); + } else if (type == COEX_ASSOCIATE_START) { + coex_stat->wl_hi_pri_task1 = true; ++ coex_stat->wl_connecting = true; + coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2; ++ coex_stat->wl_connecting = true; ++ ieee80211_queue_delayed_work(rtwdev->hw, ++ &coex->wl_connecting_work, 2 * HZ); + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n", ++ __func__); + /* Force antenna setup for no scan result issue */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + +@@ -2254,7 +2953,10 @@ void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) + } else { + coex_stat->wl_hi_pri_task1 = false; + coex->freeze = false; ++ coex_stat->wl_connecting = false; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n", ++ __func__); + rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH); + } + } +@@ -2263,17 +2965,22 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) + { + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +- u8 para[6] = {0}; + +- if (coex->stop_dm) ++ if (coex->manual_control || coex->stop_dm) + return; + + if (type == COEX_MEDIA_CONNECT_5G) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__); ++ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA); + } else if (type == COEX_MEDIA_CONNECT) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__); ++ ++ coex_stat->wl_connecting = false; ++ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + + /* Force antenna setup for no scan result issue */ +@@ -2281,18 +2988,11 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) + + /* Set CCK Rx high Pri */ + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1); +- +- /* always enable 5ms extend if connect */ +- para[0] = COEX_H2C69_WL_LEAKAP; +- para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */ +- rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); +- coex_stat->wl_slot_extend = true; + rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA); + } else { +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); +- ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n", ++ __func__); + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0); +- + rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON); + } + +@@ -2301,28 +3001,38 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) + + void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +- struct rtw_chip_info *chip = rtwdev->chip; +- unsigned long bt_relink_time; ++ struct rtw_coex_dm *coex_dm = &coex->dm; ++ u32 bt_relink_time; + u8 i, rsp_source = 0, type; + bool inq_page = false; + + rsp_source = buf[0] & 0xf; + if (rsp_source >= COEX_BTINFO_SRC_MAX) +- rsp_source = COEX_BTINFO_SRC_WL_FW; ++ return; ++ coex_stat->cnt_bt_info_c2h[rsp_source]++; + + if (rsp_source == COEX_BTINFO_SRC_BT_IQK) { + coex_stat->bt_iqk_state = buf[1]; +- if (coex_stat->bt_iqk_state == 1) ++ if (coex_stat->bt_iqk_state == 0) + coex_stat->cnt_bt[COEX_CNT_BT_IQK]++; + else if (coex_stat->bt_iqk_state == 2) + coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n", ++ buf[1]); ++ + return; + } + + if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n", ++ buf[1], buf[2]); ++ + rtw_coex_monitor_bt_enable(rtwdev); + if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) { + coex_stat->bt_disabled_pre = coex_stat->bt_disabled; +@@ -2331,6 +3041,24 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + return; + } + ++ if (rsp_source == COEX_BTINFO_SRC_H2C60) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n", ++ buf[1], buf[2], buf[3], buf[4], buf[5]); ++ ++ for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++) ++ coex_dm->fw_tdma_para[i - 1] = buf[i]; ++ return; ++ } ++ ++ if (rsp_source == COEX_BTINFO_SRC_WL_FW) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], bt_info reply by WL FW\n"); ++ ++ rtw_coex_update_bt_link_info(rtwdev); ++ return; ++ } ++ + if (rsp_source == COEX_BTINFO_SRC_BT_RSP || + rsp_source == COEX_BTINFO_SRC_BT_ACT) { + if (coex_stat->bt_disabled) { +@@ -2339,30 +3067,36 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + ieee80211_queue_delayed_work(rtwdev->hw, + &coex->bt_reenable_work, + 15 * HZ); ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT enable detected by bt_info\n"); + } + } + +- for (i = 0; i < length; i++) { +- if (i < COEX_BTINFO_LENGTH_MAX) +- coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; +- else +- break; +- } ++ if (length != COEX_BTINFO_LENGTH) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Bt_info length = %d invalid!!\n", length); + +- if (rsp_source == COEX_BTINFO_SRC_WL_FW) { +- rtw_coex_update_bt_link_info(rtwdev); +- rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); + return; + } + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n", ++ buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); ++ ++ for (i = 0; i < COEX_BTINFO_LENGTH; i++) ++ coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; ++ + /* get the same info from bt, skip it */ + if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 && + coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 && + coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 && + coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 && + coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 && +- coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) ++ coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Return because Btinfo duplicate!!\n"); + return; ++ } + + coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1]; + coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2]; +@@ -2388,6 +3122,40 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + 4 * HZ); + } + coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3)); ++ if (chip->ble_hid_profile_support) { ++ if (coex_stat->bt_info_lb2 & BIT(5)) { ++ if (coex_stat->bt_info_hb1 & BIT(0)) { ++ /*BLE HID*/ ++ coex_stat->bt_ble_hid_exist = true; ++ } else { ++ coex_stat->bt_ble_hid_exist = false; ++ } ++ coex_stat->bt_ble_exist = false; ++ } else if (coex_stat->bt_info_hb1 & BIT(0)) { ++ /*RCU*/ ++ coex_stat->bt_ble_hid_exist = false; ++ coex_stat->bt_ble_exist = true; ++ } else { ++ coex_stat->bt_ble_hid_exist = false; ++ coex_stat->bt_ble_exist = false; ++ } ++ } else { ++ if (coex_stat->bt_info_hb1 & BIT(0)) { ++ if (coex_stat->bt_hid_slot == 1 && ++ coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx && ++ coex_stat->hi_pri_rx < 100) { ++ coex_stat->bt_ble_hid_exist = true; ++ coex_stat->bt_ble_exist = false; ++ } else { ++ coex_stat->bt_ble_hid_exist = false; ++ coex_stat->bt_ble_exist = true; ++ } ++ } else { ++ coex_stat->bt_ble_hid_exist = false; ++ coex_stat->bt_ble_exist = false; ++ } ++ } ++ + coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf; + if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1) + coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++; +@@ -2398,22 +3166,13 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + coex_stat->cnt_bt[COEX_CNT_BT_INQ]++; + + coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7)); +- if (coex_stat->bt_page) { ++ if (coex_stat->bt_page) + coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++; +- if (coex_stat->wl_linkscan_proc || +- coex_stat->wl_hi_pri_task1 || +- coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); +- else +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); +- } else { +- rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); +- } + + /* unit: % (value-100 to translate to unit: dBm in coex info) */ + if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) { + coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10; +- } else { /* original unit: dbm -> unit: % -> value-100 in coex info */ ++ } else { + if (coex_stat->bt_info_hb0 <= 127) + coex_stat->bt_rssi = 100; + else if (256 - coex_stat->bt_info_hb0 <= 100) +@@ -2422,7 +3181,6 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + coex_stat->bt_rssi = 0; + } + +- coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0)); + if (coex_stat->bt_info_hb1 & BIT(1)) + coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++; + +@@ -2432,11 +3190,14 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + if (coex_stat->bt_reenable) + bt_relink_time = 6 * HZ; + else +- bt_relink_time = 2 * HZ; ++ bt_relink_time = 1 * HZ; + + ieee80211_queue_delayed_work(rtwdev->hw, + &coex->bt_relink_work, + bt_relink_time); ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], Re-Link start in BT info!!\n"); + } + + if (coex_stat->bt_info_hb1 & BIT(3)) +@@ -2448,8 +3209,21 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++; + + coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7)); ++ /* for multi_link = 0 but bt pkt remain exist */ ++ /* Use PS-TDMA to protect WL RX */ ++ if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) { ++ coex_stat->bt_multi_link_remain = true; ++ ieee80211_queue_delayed_work(rtwdev->hw, ++ &coex->bt_multi_link_remain_work, ++ 3 * HZ); ++ } ++ coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link; ++ + /* resend wifi info to bt, it is reset and lost the info */ +- if ((coex_stat->bt_info_hb1 & BIT(1))) { ++ if (coex_stat->bt_info_hb1 & BIT(1)) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n"); ++ + if (coex_stat->wl_connected) + type = COEX_MEDIA_CONNECT; + else +@@ -2459,8 +3233,11 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + + /* if ignore_wlan_act && not set_up_link */ + if ((coex_stat->bt_info_hb1 & BIT(3)) && +- (!(coex_stat->bt_info_hb1 & BIT(2)))) ++ (!(coex_stat->bt_info_hb1 & BIT(2)))) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); + rtw_coex_ignore_wlan_act(rtwdev, false); ++ } + + coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0)); + if (coex_stat->bt_info_hb2 & BIT(1)) +@@ -2472,7 +3249,7 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6; + if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2) + coex_stat->bt_418_hid_exist = true; +- else if (coex_stat->bt_hid_pair_num == 0) ++ else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1) + coex_stat->bt_418_hid_exist = false; + + if ((coex_stat->bt_info_lb2 & 0x49) == 0x49) +@@ -2486,6 +3263,135 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); + } + ++#define COEX_BT_HIDINFO_MTK 0x46 ++static const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72}; ++static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f}; ++ ++void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_coex_hid *hidinfo; ++ struct rtw_coex_hid_info_a *hida; ++ struct rtw_coex_hid_handle_list *hl, *bhl; ++ u8 sub_id = buf[2], gamehid_cnt = 0, handle, i; ++ bool cur_game_hid_exist, complete; ++ ++ if (!chip->wl_mimo_ps_support && ++ (sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A)) ++ return; ++ ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id); ++ ++ switch (sub_id) { ++ case COEX_BT_HIDINFO_LIST: ++ hl = &coex_stat->hid_handle_list; ++ bhl = (struct rtw_coex_hid_handle_list *)buf; ++ if (!memcmp(hl, bhl, sizeof(*hl))) ++ return; ++ coex_stat->hid_handle_list = *bhl; ++ memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info)); ++ for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { ++ hidinfo = &coex_stat->hid_info[i]; ++ if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON && ++ hl->handle[i] != 0) ++ hidinfo->hid_handle = hl->handle[i]; ++ } ++ break; ++ case COEX_BT_HIDINFO_A: ++ hida = (struct rtw_coex_hid_info_a *)buf; ++ handle = hida->handle; ++ for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { ++ hidinfo = &coex_stat->hid_info[i]; ++ if (hidinfo->hid_handle == handle) { ++ hidinfo->hid_vendor = hida->vendor; ++ memcpy(hidinfo->hid_name, hida->name, ++ sizeof(hidinfo->hid_name)); ++ hidinfo->hid_info_completed = true; ++ break; ++ } ++ } ++ break; ++ } ++ for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { ++ hidinfo = &coex_stat->hid_info[i]; ++ complete = hidinfo->hid_info_completed; ++ handle = hidinfo->hid_handle; ++ if (!complete || handle == COEX_BT_HIDINFO_NOTCON || ++ handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) { ++ hidinfo->is_game_hid = false; ++ continue; ++ } ++ ++ if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) { ++ if ((memcmp(hidinfo->hid_name, ++ coex_bt_hidinfo_ps, ++ COEX_BT_HIDINFO_NAME)) == 0) ++ hidinfo->is_game_hid = true; ++ else if ((memcmp(hidinfo->hid_name, ++ coex_bt_hidinfo_xb, ++ COEX_BT_HIDINFO_NAME)) == 0) ++ hidinfo->is_game_hid = true; ++ else ++ hidinfo->is_game_hid = false; ++ } else { ++ hidinfo->is_game_hid = false; ++ } ++ if (hidinfo->is_game_hid) ++ gamehid_cnt++; ++ } ++ ++ if (gamehid_cnt > 0) ++ cur_game_hid_exist = true; ++ else ++ cur_game_hid_exist = false; ++ ++ if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) { ++ coex_stat->bt_game_hid_exist = cur_game_hid_exist; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], HID info changed!bt_game_hid_exist = %d!\n", ++ coex_stat->bt_game_hid_exist); ++ rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS); ++ } ++} ++ ++void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ struct rtw_coex_hid *hidinfo; ++ u8 i, handle; ++ bool complete; ++ ++ if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips || ++ (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl)) ++ return; ++ ++ if (!coex_stat->bt_hid_exist && ++ !((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) && ++ (coex_stat->hi_pri_tx + coex_stat->hi_pri_rx > ++ COEX_BT_GAMEHID_CNT))) ++ return; ++ ++ rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0); ++ ++ for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { ++ hidinfo = &coex_stat->hid_info[i]; ++ complete = hidinfo->hid_info_completed; ++ handle = hidinfo->hid_handle; ++ if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON || ++ handle >= COEX_BT_BLE_HANDLE_THRS || complete) ++ continue; ++ ++ rtw_fw_coex_query_hid_info(rtwdev, ++ COEX_BT_HIDINFO_A, ++ handle); ++ } ++} ++ + void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + { + struct rtw_coex *coex = &rtwdev->coex; +@@ -2493,6 +3399,9 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + u8 val; + int i; + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, ++ "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n", ++ buf, length); + if (WARN(length < 8, "invalid wl info c2h length\n")) + return; + +@@ -2504,7 +3413,7 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + if (buf[i] >= val) + coex_stat->wl_fw_dbg_info[i] = buf[i] - val; + else +- coex_stat->wl_fw_dbg_info[i] = val - buf[i]; ++ coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i]; + + coex_stat->wl_fw_dbg_info_pre[i] = buf[i]; + } +@@ -2514,14 +3423,20 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) + rtw_coex_wl_ccklock_detect(rtwdev); + } + +-void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev) ++void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type) + { +- struct rtw_coex *coex = &rtwdev->coex; ++ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); ++} ++ ++void rtw_coex_wl_status_check(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; + +- if (coex->stop_dm) ++ if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) || ++ coex_stat->wl_under_ips) + return; + +- rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); ++ rtw_coex_monitor_bt_ctr(rtwdev); + } + + void rtw_coex_bt_relink_work(struct work_struct *work) +@@ -2585,6 +3500,41 @@ void rtw_coex_bt_remain_work(struct work_struct *work) + mutex_unlock(&rtwdev->mutex); + } + ++void rtw_coex_wl_connecting_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ++ coex.wl_connecting_work.work); ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; ++ ++ mutex_lock(&rtwdev->mutex); ++ coex_stat->wl_connecting = false; ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n"); ++ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); ++ mutex_unlock(&rtwdev->mutex); ++} ++ ++void rtw_coex_bt_multi_link_remain_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ++ coex.bt_multi_link_remain_work.work); ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; ++ ++ mutex_lock(&rtwdev->mutex); ++ coex_stat->bt_multi_link_remain = false; ++ mutex_unlock(&rtwdev->mutex); ++} ++ ++void rtw_coex_wl_ccklock_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ++ coex.wl_ccklock_work.work); ++ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; ++ ++ mutex_lock(&rtwdev->mutex); ++ coex_stat->wl_cck_lock = false; ++ mutex_unlock(&rtwdev->mutex); ++} ++ + #ifdef CONFIG_RTW88_DEBUGFS + #define INFO_SIZE 80 + +@@ -2628,6 +3578,81 @@ static const char *rtw_coex_get_reason_string(u8 reason) + } + } + ++static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0, ++ u32 wl_reg_6c4) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 ans = 0xFF; ++ u8 n, i; ++ u32 load_bt_val; ++ u32 load_wl_val; ++ bool share_ant = efuse->share_ant; ++ ++ if (share_ant) ++ n = chip->table_sant_num; ++ else ++ n = chip->table_nsant_num; ++ ++ for (i = 0; i < n; i++) { ++ if (share_ant) { ++ load_bt_val = chip->table_sant[i].bt; ++ load_wl_val = chip->table_sant[i].wl; ++ } else { ++ load_bt_val = chip->table_nsant[i].bt; ++ load_wl_val = chip->table_nsant[i].wl; ++ } ++ ++ if (wl_reg_6c0 == load_bt_val && ++ wl_reg_6c4 == load_wl_val) { ++ ans = i; ++ if (!share_ant) ++ ans += 100; ++ break; ++ } ++ } ++ ++ return ans; ++} ++ ++static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ u8 ans = 0xFF; ++ u8 n, i, j; ++ u8 load_cur_tab_val; ++ bool valid = false; ++ bool share_ant = efuse->share_ant; ++ ++ if (share_ant) ++ n = chip->tdma_sant_num; ++ else ++ n = chip->tdma_nsant_num; ++ ++ for (i = 0; i < n; i++) { ++ valid = false; ++ for (j = 0; j < 5; j++) { ++ if (share_ant) ++ load_cur_tab_val = chip->tdma_sant[i].para[j]; ++ else ++ load_cur_tab_val = chip->tdma_nsant[i].para[j]; ++ ++ if (*(tdma_para + j) != load_cur_tab_val) ++ break; ++ ++ if (j == 4) ++ valid = true; ++ } ++ if (valid) { ++ ans = i; ++ break; ++ } ++ } ++ ++ return ans; ++} ++ + static int rtw_coex_addr_info(struct rtw_dev *rtwdev, + const struct rtw_reg_domain *reg, + char addr_info[], int n) +@@ -2710,7 +3735,7 @@ static int rtw_coex_val_info(struct rtw_dev *rtwdev, + + static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_reg_domain *reg; + char addr_info[INFO_SIZE]; + int n_addr = 0; +@@ -2756,6 +3781,7 @@ static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev, + + payload = get_payload_from_coex_resp(skb); + *val = GET_COEX_RESP_BT_REG_VAL(payload); ++ dev_kfree_skb_any(skb); + + return true; + } +@@ -2766,19 +3792,17 @@ static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev, + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; +- bool ret = false; + + req.op_code = BT_MP_INFO_OP_PATCH_VER; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) +- goto out; ++ return false; + + payload = get_payload_from_coex_resp(skb); + *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload); +- ret = true; ++ dev_kfree_skb_any(skb); + +-out: +- return ret; ++ return true; + } + + static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev, +@@ -2787,19 +3811,17 @@ static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev, + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; +- bool ret = false; + + req.op_code = BT_MP_INFO_OP_SUPP_VER; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) +- goto out; ++ return false; + + payload = get_payload_from_coex_resp(skb); + *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload); +- ret = true; ++ dev_kfree_skb_any(skb); + +-out: +- return ret; ++ return true; + } + + static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev, +@@ -2808,19 +3830,17 @@ static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev, + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; +- bool ret = false; + + req.op_code = BT_MP_INFO_OP_SUPP_FEAT; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) +- goto out; ++ return false; + + payload = get_payload_from_coex_resp(skb); + *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload); +- ret = true; ++ dev_kfree_skb_any(skb); + +-out: +- return ret; ++ return true; + } + + struct rtw_coex_sta_stat_iter_data { +@@ -2873,9 +3893,23 @@ static void rtw_coex_vif_stat_iter(void *data, u8 *mac, + &sta_iter_data); + } + ++#define case_WLINK(src) \ ++ case COEX_WLINK_##src: return #src ++ ++static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode) ++{ ++ switch (coex_wl_link_mode) { ++ case_WLINK(2G1PORT); ++ case_WLINK(5G); ++ case_WLINK(2GFREE); ++ default: ++ return "Unknown"; ++ } ++} ++ + void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; +@@ -2889,19 +3923,16 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + u16 score_board_WB, score_board_BW; + u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc; + u32 lte_coex, bt_coex; +- u32 bt_hi_pri, bt_lo_pri; + int i; + + score_board_BW = rtw_coex_read_scbd(rtwdev); + score_board_WB = coex_stat->score_board; +- wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0); +- wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4); +- wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8); +- wl_reg_6cc = rtw_read32(rtwdev, 0x6cc); +- wl_reg_778 = rtw_read32(rtwdev, 0x778); +- bt_hi_pri = rtw_read32(rtwdev, 0x770); +- bt_lo_pri = rtw_read32(rtwdev, 0x774); +- rtw_write8(rtwdev, 0x76e, 0xc); ++ wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0); ++ wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1); ++ wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE); ++ wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H); ++ wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL); ++ + sys_lte = rtw_read8(rtwdev, 0x73); + lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); + bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); +@@ -2919,9 +3950,24 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + coex_stat->bt_mailbox_reply = true; + } + ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tBT Coexist info %x\n", chip->id); + seq_printf(m, "**********************************************\n"); ++ ++ if (coex->manual_control) { ++ seq_puts(m, "============[Under Manual Control]============\n"); ++ seq_puts(m, "==========================================\n"); ++ ++ } else if (coex->stop_dm) { ++ seq_puts(m, "============[Coex is STOPPED]============\n"); ++ seq_puts(m, "==========================================\n"); ++ ++ } else if (coex->freeze) { ++ seq_puts(m, "============[coex_freeze]============\n"); ++ seq_puts(m, "==========================================\n"); ++ } ++ + seq_printf(m, "%-40s = %s/ %d\n", + "Mech/ RFE", + efuse->share_ant ? "Shared" : "Non-Shared", +@@ -2938,15 +3984,17 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + coex_stat->bt_slave ? "Slave" : "Master", + coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH], + coex_dm->ignore_wl_act); +- seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n", +- "WL FW/ BT FW/ KT", ++ seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n", ++ "WL FW/ BT FW/ BT FW Desired/ KT", + fw->version, fw->sub_version, +- coex_stat->patch_ver, coex_stat->kt_ver + 65); ++ coex_stat->patch_ver, ++ chip->wl_fw_desired_ver, coex_stat->kt_ver + 65); + seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n", + "AFH Map", + coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1], + coex_dm->wl_ch_info[2], hal->current_channel); + ++ rtw_debugfs_get_simple_phy_info(m); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tBT Status\n"); + seq_printf(m, "**********************************************\n"); +@@ -2965,6 +4013,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + coex_stat->bt_hid_exist ? + (coex_stat->bt_ble_exist ? "HID(RCU)," : + coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" : ++ coex_stat->bt_ble_hid_exist ? "HID(BLE)" : + "HID(2/18),") : "", + coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ? + "OPP," : "PAN," : "", +@@ -2989,8 +4038,8 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + score_board_WB, score_board_BW); + seq_printf(m, "%-40s = %u/%u, %u/%u\n", + "Hi-Pri TX/RX, Lo-Pri TX/RX", +- bt_hi_pri & 0xffff, bt_hi_pri >> 16, +- bt_lo_pri & 0xffff, bt_lo_pri >> 16); ++ coex_stat->hi_pri_tx, coex_stat->hi_pri_rx, ++ coex_stat->lo_pri_tx, coex_stat->lo_pri_rx); + for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++) + seq_printf(m, "%-40s = %7ph\n", + rtw_coex_get_bt_info_src_string(i), +@@ -3007,7 +4056,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput); + seq_printf(m, "%-40s = %u/ %u/ %u\n", + "IPS/ Low Power/ PS mode", +- test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags), ++ !test_bit(RTW_FLAG_POWERON, rtwdev->flags), + test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags), + rtwdev->lps_conf.mode); + +@@ -3015,20 +4064,45 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + vif_iter_data.file = m; + rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data); + +- seq_printf(m, "**********************************************\n"); +- seq_printf(m, "\t\tMechanism\n"); +- seq_printf(m, "**********************************************\n"); +- seq_printf(m, "%-40s = %5ph (case-%d)\n", +- "TDMA", +- coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma); +- seq_printf(m, "%-40s = %d\n", +- "Timer base", coex_stat->tdma_timer_base); +- seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n", ++ if (coex->manual_control) { ++ seq_printf(m, "**********************************************\n"); ++ seq_printf(m, "\t\tMechanism (Under Manual)\n"); ++ seq_printf(m, "**********************************************\n"); ++ seq_printf(m, "%-40s = %5ph (%d)\n", ++ "TDMA Now", ++ coex_dm->fw_tdma_para, ++ rtw_coex_get_tdma_index(rtwdev, ++ &coex_dm->fw_tdma_para[0])); ++ } else { ++ seq_printf(m, "**********************************************\n"); ++ seq_printf(m, "\t\tMechanism\n"); ++ seq_printf(m, "**********************************************\n"); ++ seq_printf(m, "%-40s = %5ph (case-%d)\n", ++ "TDMA", ++ coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma); ++ } ++ seq_printf(m, "%-40s = %s/ %s/ %d\n", ++ "Coex Mode/Free Run/Timer base", ++ rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode), ++ coex->freerun ? "Yes" : "No", ++ coex_stat->tdma_timer_base); ++ seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n", + "Table/ 0x6c0/ 0x6c4/ 0x6c8", +- coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8); +- seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n", +- "0x778/ 0x6cc/ Reason", +- wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason)); ++ coex_dm->cur_table, ++ rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4), ++ wl_reg_6c0, wl_reg_6c4, wl_reg_6c8); ++ seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n", ++ "0x778/ 0x6cc/ Run Count/ Reason", ++ wl_reg_778, wl_reg_6cc, ++ coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN], ++ rtw_coex_get_reason_string(reason)); ++ seq_printf(m, "%-40s = %3ph\n", ++ "AFH Map to BT", ++ coex_dm->wl_ch_info); ++ seq_printf(m, "%-40s = %s/ %d\n", ++ "AntDiv/ BtCtrlLPS/ g_busy", ++ coex_stat->wl_force_lps_ctrl ? "On" : "Off", ++ coex_stat->wl_gl_busy); + seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n", + "Null All/ Retry/ Ack/ BT Empty/ BT Late", + coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2], +@@ -3040,6 +4114,12 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + coex_stat->wl_fw_dbg_info[7], + coex_stat->wl_slot_extend ? "Yes" : "No", + coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]); ++ seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n", ++ "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl", ++ coex_dm->cur_wl_pwr_lvl, ++ coex_dm->cur_bt_pwr_lvl, ++ coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off", ++ coex_dm->cur_bt_lna_lvl); + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tHW setting\n"); +@@ -3074,5 +4154,22 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) + coex_stat->wl_noisy_level); + + rtw_coex_set_coexinfo_hw(rtwdev, m); ++ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", ++ "EVM A/ EVM B/ SNR A/ SNR B", ++ -dm_info->rx_evm_dbm[RF_PATH_A], ++ -dm_info->rx_evm_dbm[RF_PATH_B], ++ -dm_info->rx_snr[RF_PATH_A], ++ -dm_info->rx_snr[RF_PATH_B]); ++ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", ++ "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA", ++ dm_info->cck_cca_cnt, dm_info->cck_fa_cnt, ++ dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt); ++ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac", ++ dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt, ++ dm_info->ht_ok_cnt, dm_info->vht_ok_cnt); ++ seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac", ++ dm_info->cck_err_cnt, dm_info->ofdm_err_cnt, ++ dm_info->ht_err_cnt, dm_info->vht_err_cnt); ++ + } + #endif /* CONFIG_RTW88_DEBUGFS */ +diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h +index 44720fdfc053..57cf29da9ea4 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.h ++++ b/drivers/net/wireless/realtek/rtw88/coex.h +@@ -5,17 +5,13 @@ + #ifndef __RTW_COEX_H__ + #define __RTW_COEX_H__ + +-/* BT profile map bit definition */ +-#define BPM_HFP BIT(0) +-#define BPM_HID BIT(1) +-#define BPM_A2DP BIT(2) +-#define BPM_PAN BIT(3) +- ++#define COEX_CCK_2 0x1 + #define COEX_RESP_ACK_BY_WL_FW 0x1 + #define COEX_REQUEST_TIMEOUT msecs_to_jiffies(10) + + #define COEX_MIN_DELAY 10 /* delay unit in ms */ + #define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */ ++#define COEX_BT_GAMEHID_CNT 800 + + #define COEX_RF_OFF 0x0 + #define COEX_RF_ON 0x1 +@@ -27,10 +23,19 @@ + #define COEX_H2C69_TDMA_SLOT 0xb + #define PARA1_H2C69_TDMA_4SLOT 0xc1 + #define PARA1_H2C69_TDMA_2SLOT 0x1 ++#define PARA1_H2C69_TBTT_TIMES GENMASK(5, 0) ++#define PARA1_H2C69_TBTT_DIV100 BIT(7) ++ ++#define COEX_H2C69_TOGGLE_TABLE_A 0xd ++#define COEX_H2C69_TOGGLE_TABLE_B 0x7 + + #define TDMA_4SLOT BIT(8) + ++#define TDMA_TIMER_TYPE_2SLOT 0 ++#define TDMA_TIMER_TYPE_4SLOT 3 ++ + #define COEX_RSSI_STEP 4 ++ + #define COEX_RSSI_HIGH(rssi) \ + ({ typeof(rssi) __rssi__ = rssi; \ + (__rssi__ == COEX_RSSI_STATE_HIGH || \ +@@ -146,9 +151,29 @@ enum coex_algorithm { + COEX_ALGO_MAX + }; + ++enum coex_bt_profile { ++ BPM_NOPROFILE = 0, ++ BPM_HFP = BIT(0), ++ BPM_HID = BIT(1), ++ BPM_A2DP = BIT(2), ++ BPM_PAN = BIT(3), ++ BPM_HID_HFP = BPM_HID | BPM_HFP, ++ BPM_A2DP_HFP = BPM_A2DP | BPM_HFP, ++ BPM_A2DP_HID = BPM_A2DP | BPM_HID, ++ BPM_A2DP_HID_HFP = BPM_A2DP | BPM_HID | BPM_HFP, ++ BPM_PAN_HFP = BPM_PAN | BPM_HFP, ++ BPM_PAN_HID = BPM_PAN | BPM_HID, ++ BPM_PAN_HID_HFP = BPM_PAN | BPM_HID | BPM_HFP, ++ BPM_PAN_A2DP = BPM_PAN | BPM_A2DP, ++ BPM_PAN_A2DP_HFP = BPM_PAN | BPM_A2DP | BPM_HFP, ++ BPM_PAN_A2DP_HID = BPM_PAN | BPM_A2DP | BPM_HID, ++ BPM_PAN_A2DP_HID_HFP = BPM_PAN | BPM_A2DP | BPM_HID | BPM_HFP, ++}; ++ + enum coex_wl_link_mode { + COEX_WLINK_2G1PORT = 0x0, + COEX_WLINK_5G = 0x3, ++ COEX_WLINK_2GFREE = 0x7, + COEX_WLINK_MAX + }; + +@@ -302,7 +327,7 @@ struct coex_rf_para { + + static inline void rtw_coex_set_init(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_init(rtwdev); + } +@@ -310,7 +335,7 @@ static inline void rtw_coex_set_init(struct rtw_dev *rtwdev) + static inline + void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->ops->coex_set_ant_switch) + return; +@@ -320,28 +345,28 @@ void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type) + + static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_gnt_fix(rtwdev); + } + + static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_gnt_debug(rtwdev); + } + + static inline void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_rfe_type(rtwdev); + } + + static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr); + } +@@ -349,7 +374,7 @@ static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) + static inline + void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain); + } +@@ -365,19 +390,33 @@ void rtw_coex_bt_reenable_work(struct work_struct *work); + void rtw_coex_defreeze_work(struct work_struct *work); + void rtw_coex_wl_remain_work(struct work_struct *work); + void rtw_coex_bt_remain_work(struct work_struct *work); ++void rtw_coex_wl_connecting_work(struct work_struct *work); ++void rtw_coex_bt_multi_link_remain_work(struct work_struct *work); ++void rtw_coex_wl_ccklock_work(struct work_struct *work); + + void rtw_coex_power_on_setting(struct rtw_dev *rtwdev); ++void rtw_coex_power_off_setting(struct rtw_dev *rtwdev); + void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only); + void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type); + void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type); + void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type); +-void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 action); +-void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 status); +-void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 len); ++void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type); ++void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type); ++void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length); ++void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length); + void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length); + void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type); +-void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev); +- ++void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type); ++void rtw_coex_wl_status_check(struct rtw_dev *rtwdev); ++void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev); + void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m); + ++static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev) ++{ ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; ++ ++ return coex_stat->bt_disabled; ++} ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/compiler.h b/drivers/net/wireless/realtek/rtw88/compiler.h +new file mode 100644 +index 000000000000..adcd51c87e4d +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/compiler.h +@@ -0,0 +1,552 @@ ++#ifndef __LINUX_COMPILER_H ++#define __LINUX_COMPILER_H ++ ++#ifndef __ASSEMBLY__ ++ ++#ifdef __CHECKER__ ++# define __user __attribute__((noderef, address_space(1))) ++# define __kernel __attribute__((address_space(0))) ++# define __safe __attribute__((safe)) ++# define __force __attribute__((force)) ++# define __nocast __attribute__((nocast)) ++# define __iomem __attribute__((noderef, address_space(2))) ++# define __must_hold(x) __attribute__((context(x,1,1))) ++# define __acquires(x) __attribute__((context(x,0,1))) ++# define __releases(x) __attribute__((context(x,1,0))) ++# define __acquire(x) __context__(x,1) ++# define __release(x) __context__(x,-1) ++# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) ++# define __percpu __attribute__((noderef, address_space(3))) ++#ifdef CONFIG_SPARSE_RCU_POINTER ++# define __rcu __attribute__((noderef, address_space(4))) ++#else /* CONFIG_SPARSE_RCU_POINTER */ ++# define __rcu ++#endif /* CONFIG_SPARSE_RCU_POINTER */ ++# define __private __attribute__((noderef)) ++extern void __chk_user_ptr(const volatile void __user *); ++extern void __chk_io_ptr(const volatile void __iomem *); ++# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member)) ++#else /* __CHECKER__ */ ++# define __user ++# define __kernel ++# define __safe ++# define __force ++# define __nocast ++# define __iomem ++# define __chk_user_ptr(x) (void)0 ++# define __chk_io_ptr(x) (void)0 ++# define __builtin_warning(x, y...) (1) ++# define __must_hold(x) ++# define __acquires(x) ++# define __releases(x) ++# define __acquire(x) (void)0 ++# define __release(x) (void)0 ++# define __cond_lock(x,c) (c) ++# define __percpu ++# define __rcu ++# define __private ++# define ACCESS_PRIVATE(p, member) ((p)->member) ++#endif /* __CHECKER__ */ ++ ++/* Indirect macros required for expanded argument pasting, eg. __LINE__. */ ++#define ___PASTE(a,b) a##b ++#define __PASTE(a,b) ___PASTE(a,b) ++ ++#ifdef __KERNEL__ ++ ++#ifdef __GNUC__ ++#include ++#endif ++ ++#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__) ++#define notrace __attribute__((hotpatch(0,0))) ++#else ++#define notrace __attribute__((no_instrument_function)) ++#endif ++ ++/* Intel compiler defines __GNUC__. So we will overwrite implementations ++ * coming from above header files here ++ */ ++#ifdef __INTEL_COMPILER ++# include ++#endif ++ ++/* Clang compiler defines __GNUC__. So we will overwrite implementations ++ * coming from above header files here ++ */ ++#ifdef __clang__ ++#include ++#endif ++ ++/* ++ * Generic compiler-dependent macros required for kernel ++ * build go below this comment. Actual compiler/compiler version ++ * specific implementations come from the above header files ++ */ ++ ++struct ftrace_branch_data { ++ const char *func; ++ const char *file; ++ unsigned line; ++ union { ++ struct { ++ unsigned long correct; ++ unsigned long incorrect; ++ }; ++ struct { ++ unsigned long miss; ++ unsigned long hit; ++ }; ++ unsigned long miss_hit[2]; ++ }; ++}; ++ ++/* ++ * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code ++ * to disable branch tracing on a per file basis. ++ */ ++#if defined(CONFIG_TRACE_BRANCH_PROFILING) \ ++ && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__) ++void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); ++ ++#define likely_notrace(x) __builtin_expect(!!(x), 1) ++#define unlikely_notrace(x) __builtin_expect(!!(x), 0) ++ ++#define __branch_check__(x, expect) ({ \ ++ int ______r; \ ++ static struct ftrace_branch_data \ ++ __attribute__((__aligned__(4))) \ ++ __attribute__((section("_ftrace_annotated_branch"))) \ ++ ______f = { \ ++ .func = __func__, \ ++ .file = __FILE__, \ ++ .line = __LINE__, \ ++ }; \ ++ ______r = likely_notrace(x); \ ++ ftrace_likely_update(&______f, ______r, expect); \ ++ ______r; \ ++ }) ++ ++/* ++ * Using __builtin_constant_p(x) to ignore cases where the return ++ * value is always the same. This idea is taken from a similar patch ++ * written by Daniel Walker. ++ */ ++# ifndef likely ++# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1)) ++# endif ++# ifndef unlikely ++# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ++# endif ++ ++#ifdef CONFIG_PROFILE_ALL_BRANCHES ++/* ++ * "Define 'is'", Bill Clinton ++ * "Define 'if'", Steven Rostedt ++ */ ++#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ++#define __trace_if(cond) \ ++ if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ++ ({ \ ++ int ______r; \ ++ static struct ftrace_branch_data \ ++ __attribute__((__aligned__(4))) \ ++ __attribute__((section("_ftrace_branch"))) \ ++ ______f = { \ ++ .func = __func__, \ ++ .file = __FILE__, \ ++ .line = __LINE__, \ ++ }; \ ++ ______r = !!(cond); \ ++ ______f.miss_hit[______r]++; \ ++ ______r; \ ++ })) ++#endif /* CONFIG_PROFILE_ALL_BRANCHES */ ++ ++#else ++# define likely(x) __builtin_expect(!!(x), 1) ++# define unlikely(x) __builtin_expect(!!(x), 0) ++#endif ++ ++/* Optimization barrier */ ++#ifndef barrier ++# define barrier() __memory_barrier() ++#endif ++ ++#ifndef barrier_data ++# define barrier_data(ptr) barrier() ++#endif ++ ++/* Unreachable code */ ++#ifndef unreachable ++# define unreachable() do { } while (1) ++#endif ++ ++/* ++ * KENTRY - kernel entry point ++ * This can be used to annotate symbols (functions or data) that are used ++ * without their linker symbol being referenced explicitly. For example, ++ * interrupt vector handlers, or functions in the kernel image that are found ++ * programatically. ++ * ++ * Not required for symbols exported with EXPORT_SYMBOL, or initcalls. Those ++ * are handled in their own way (with KEEP() in linker scripts). ++ * ++ * KENTRY can be avoided if the symbols in question are marked as KEEP() in the ++ * linker script. For example an architecture could KEEP() its entire ++ * boot/exception vector code rather than annotate each function and data. ++ */ ++#ifndef KENTRY ++# define KENTRY(sym) \ ++ extern typeof(sym) sym; \ ++ static const unsigned long __kentry_##sym \ ++ __used \ ++ __attribute__((section("___kentry" "+" #sym ), used)) \ ++ = (unsigned long)&sym; ++#endif ++ ++#ifndef RELOC_HIDE ++# define RELOC_HIDE(ptr, off) \ ++ ({ unsigned long __ptr; \ ++ __ptr = (unsigned long) (ptr); \ ++ (typeof(ptr)) (__ptr + (off)); }) ++#endif ++ ++#ifndef OPTIMIZER_HIDE_VAR ++#define OPTIMIZER_HIDE_VAR(var) barrier() ++#endif ++ ++/* Not-quite-unique ID. */ ++#ifndef __UNIQUE_ID ++# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__) ++#endif ++ ++#include ++ ++#define __READ_ONCE_SIZE \ ++({ \ ++ switch (size) { \ ++ case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \ ++ case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \ ++ case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \ ++ case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \ ++ default: \ ++ barrier(); \ ++ __builtin_memcpy((void *)res, (const void *)p, size); \ ++ barrier(); \ ++ } \ ++}) ++ ++static __always_inline ++void __read_once_size(const volatile void *p, void *res, int size) ++{ ++ __READ_ONCE_SIZE; ++} ++ ++#ifdef CONFIG_KASAN ++/* ++ * This function is not 'inline' because __no_sanitize_address confilcts ++ * with inlining. Attempt to inline it may cause a build failure. ++ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 ++ * '__maybe_unused' allows us to avoid defined-but-not-used warnings. ++ */ ++static __no_sanitize_address __maybe_unused ++void __read_once_size_nocheck(const volatile void *p, void *res, int size) ++{ ++ __READ_ONCE_SIZE; ++} ++#else ++static __always_inline ++void __read_once_size_nocheck(const volatile void *p, void *res, int size) ++{ ++ __READ_ONCE_SIZE; ++} ++#endif ++ ++static __always_inline void __write_once_size(volatile void *p, void *res, int size) ++{ ++ switch (size) { ++ case 1: *(volatile __u8 *)p = *(__u8 *)res; break; ++ case 2: *(volatile __u16 *)p = *(__u16 *)res; break; ++ case 4: *(volatile __u32 *)p = *(__u32 *)res; break; ++ case 8: *(volatile __u64 *)p = *(__u64 *)res; break; ++ default: ++ barrier(); ++ __builtin_memcpy((void *)p, (const void *)res, size); ++ barrier(); ++ } ++} ++ ++/* ++ * Prevent the compiler from merging or refetching reads or writes. The ++ * compiler is also forbidden from reordering successive instances of ++ * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the ++ * compiler is aware of some particular ordering. One way to make the ++ * compiler aware of ordering is to put the two invocations of READ_ONCE, ++ * WRITE_ONCE or ACCESS_ONCE() in different C statements. ++ * ++ * In contrast to ACCESS_ONCE these two macros will also work on aggregate ++ * data types like structs or unions. If the size of the accessed data ++ * type exceeds the word size of the machine (e.g., 32 bits or 64 bits) ++ * READ_ONCE() and WRITE_ONCE() will fall back to memcpy(). There's at ++ * least two memcpy()s: one for the __builtin_memcpy() and then one for ++ * the macro doing the copy of variable - '__u' allocated on the stack. ++ * ++ * Their two major use cases are: (1) Mediating communication between ++ * process-level code and irq/NMI handlers, all running on the same CPU, ++ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise ++ * mutilate accesses that either do not require ordering or that interact ++ * with an explicit memory barrier or atomic instruction that provides the ++ * required ordering. ++ */ ++ ++#define __READ_ONCE(x, check) \ ++({ \ ++ union { typeof(x) __val; char __c[1]; } __u; \ ++ if (check) \ ++ __read_once_size(&(x), __u.__c, sizeof(x)); \ ++ else \ ++ __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \ ++ __u.__val; \ ++}) ++#define READ_ONCE(x) __READ_ONCE(x, 1) ++ ++/* ++ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need ++ * to hide memory access from KASAN. ++ */ ++#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0) ++ ++#define WRITE_ONCE(x, val) \ ++({ \ ++ union { typeof(x) __val; char __c[1]; } __u = \ ++ { .__val = (__force typeof(x)) (val) }; \ ++ __write_once_size(&(x), __u.__c, sizeof(x)); \ ++ __u.__val; \ ++}) ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* __ASSEMBLY__ */ ++ ++#ifdef __KERNEL__ ++/* ++ * Allow us to mark functions as 'deprecated' and have gcc emit a nice ++ * warning for each use, in hopes of speeding the functions removal. ++ * Usage is: ++ * int __deprecated foo(void) ++ */ ++#ifndef __deprecated ++# define __deprecated /* unimplemented */ ++#endif ++ ++#ifdef MODULE ++#define __deprecated_for_modules __deprecated ++#else ++#define __deprecated_for_modules ++#endif ++ ++#ifndef __must_check ++#define __must_check ++#endif ++ ++#ifndef CONFIG_ENABLE_MUST_CHECK ++#undef __must_check ++#define __must_check ++#endif ++#ifndef CONFIG_ENABLE_WARN_DEPRECATED ++#undef __deprecated ++#undef __deprecated_for_modules ++#define __deprecated ++#define __deprecated_for_modules ++#endif ++ ++#ifndef __malloc ++#define __malloc ++#endif ++ ++/* ++ * Allow us to avoid 'defined but not used' warnings on functions and data, ++ * as well as force them to be emitted to the assembly file. ++ * ++ * As of gcc 3.4, static functions that are not marked with attribute((used)) ++ * may be elided from the assembly file. As of gcc 3.4, static data not so ++ * marked will not be elided, but this may change in a future gcc version. ++ * ++ * NOTE: Because distributions shipped with a backported unit-at-a-time ++ * compiler in gcc 3.3, we must define __used to be __attribute__((used)) ++ * for gcc >=3.3 instead of 3.4. ++ * ++ * In prior versions of gcc, such functions and data would be emitted, but ++ * would be warned about except with attribute((unused)). ++ * ++ * Mark functions that are referenced only in inline assembly as __used so ++ * the code is emitted even though it appears to be unreferenced. ++ */ ++#ifndef __used ++# define __used /* unimplemented */ ++#endif ++ ++#ifndef __maybe_unused ++# define __maybe_unused /* unimplemented */ ++#endif ++ ++#ifndef __always_unused ++# define __always_unused /* unimplemented */ ++#endif ++ ++#ifndef noinline ++#define noinline ++#endif ++ ++/* ++ * Rather then using noinline to prevent stack consumption, use ++ * noinline_for_stack instead. For documentation reasons. ++ */ ++#define noinline_for_stack noinline ++ ++#ifndef __always_inline ++#define __always_inline inline ++#endif ++ ++#endif /* __KERNEL__ */ ++ ++/* ++ * From the GCC manual: ++ * ++ * Many functions do not examine any values except their arguments, ++ * and have no effects except the return value. Basically this is ++ * just slightly more strict class than the `pure' attribute above, ++ * since function is not allowed to read global memory. ++ * ++ * Note that a function that has pointer arguments and examines the ++ * data pointed to must _not_ be declared `const'. Likewise, a ++ * function that calls a non-`const' function usually must not be ++ * `const'. It does not make sense for a `const' function to return ++ * `void'. ++ */ ++#ifndef __attribute_const__ ++# define __attribute_const__ /* unimplemented */ ++#endif ++ ++#ifndef __latent_entropy ++# define __latent_entropy ++#endif ++ ++/* ++ * Tell gcc if a function is cold. The compiler will assume any path ++ * directly leading to the call is unlikely. ++ */ ++ ++#ifndef __cold ++#define __cold ++#endif ++ ++/* Simple shorthand for a section definition */ ++#ifndef __section ++# define __section(S) __attribute__ ((__section__(#S))) ++#endif ++ ++#ifndef __visible ++#define __visible ++#endif ++ ++/* ++ * Assume alignment of return value. ++ */ ++#ifndef __assume_aligned ++#define __assume_aligned(a, ...) ++#endif ++ ++ ++/* Are two types/vars the same type (ignoring qualifiers)? */ ++#ifndef __same_type ++# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) ++#endif ++ ++/* Is this type a native word size -- useful for atomic operations */ ++#ifndef __native_word ++# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) ++#endif ++ ++/* Compile time object size, -1 for unknown */ ++#ifndef __compiletime_object_size ++# define __compiletime_object_size(obj) -1 ++#endif ++#ifndef __compiletime_warning ++# define __compiletime_warning(message) ++#endif ++#ifndef __compiletime_error ++# define __compiletime_error(message) ++# ifndef __CHECKER__ ++# define __compiletime_error_fallback(condition) \ ++ do { ((void)sizeof(char[1 - 2 * condition])); } while (0) ++# endif ++#endif ++#ifndef __compiletime_error_fallback ++# define __compiletime_error_fallback(condition) do { } while (0) ++#endif ++ ++/* ++ * Prevent the compiler from merging or refetching accesses. The compiler ++ * is also forbidden from reordering successive instances of ACCESS_ONCE(), ++ * but only when the compiler is aware of some particular ordering. One way ++ * to make the compiler aware of ordering is to put the two invocations of ++ * ACCESS_ONCE() in different C statements. ++ * ++ * ACCESS_ONCE will only work on scalar types. For union types, ACCESS_ONCE ++ * on a union member will work as long as the size of the member matches the ++ * size of the union and the size is smaller than word size. ++ * ++ * The major use cases of ACCESS_ONCE used to be (1) Mediating communication ++ * between process-level code and irq/NMI handlers, all running on the same CPU, ++ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise ++ * mutilate accesses that either do not require ordering or that interact ++ * with an explicit memory barrier or atomic instruction that provides the ++ * required ordering. ++ * ++ * If possible use READ_ONCE()/WRITE_ONCE() instead. ++ */ ++#define __ACCESS_ONCE(x) ({ \ ++ __maybe_unused typeof(x) __var = (__force typeof(x)) 0; \ ++ (volatile typeof(x) *)&(x); }) ++#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x)) ++ ++/** ++ * lockless_dereference() - safely load a pointer for later dereference ++ * @p: The pointer to load ++ * ++ * Similar to rcu_dereference(), but for situations where the pointed-to ++ * object's lifetime is managed by something other than RCU. That ++ * "something other" might be reference counting or simple immortality. ++ * ++ * The seemingly unused variable ___typecheck_p validates that @p is ++ * indeed a pointer type by using a pointer to typeof(*p) as the type. ++ * Taking a pointer to typeof(*p) again is needed in case p is void *. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++#define lockless_dereference(p) \ ++({ \ ++ typeof(p) _________p1 = READ_ONCE(p); \ ++ typeof(*(p)) *___typecheck_p __maybe_unused; \ ++ smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ ++ (_________p1); \ ++}) ++#else ++#define lockless_dereference(p) \ ++({ \ ++ typeof(p) _________p1 = READ_ONCE(p); \ ++ smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ ++ (_________p1); \ ++}) ++#endif ++ ++/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */ ++#ifdef CONFIG_KPROBES ++# define __kprobes __attribute__((__section__(".kprobes.text"))) ++# define nokprobe_inline __always_inline ++#else ++# define __kprobes ++# define nokprobe_inline inline ++#endif ++#endif /* __LINUX_COMPILER_H */ +diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c +index 8bb6cc8ca74e..35bc37a3c469 100644 +--- a/drivers/net/wireless/realtek/rtw88/debug.c ++++ b/drivers/net/wireless/realtek/rtw88/debug.c +@@ -10,6 +10,9 @@ + #include "fw.h" + #include "debug.h" + #include "phy.h" ++#include "reg.h" ++#include "ps.h" ++#include "regd.h" + + #ifdef CONFIG_RTW88_DEBUGFS + +@@ -34,9 +37,17 @@ struct rtw_debugfs_priv { + u32 addr; + u32 len; + } read_reg; ++ struct { ++ u8 bit; ++ } dm_cap; + }; + }; + ++static const char * const rtw_dm_cap_strs[] = { ++ [RTW_DM_CAP_NA] = "NA", ++ [RTW_DM_CAP_TXGAPK] = "TXGAPK", ++}; ++ + static int rtw_debugfs_single_show(struct seq_file *m, void *v) + { + struct rtw_debugfs_priv *debugfs_priv = m->private; +@@ -133,7 +144,9 @@ static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v) + addr = debugfs_priv->rf_addr; + mask = debugfs_priv->rf_mask; + ++ mutex_lock(&rtwdev->mutex); + val = rtw_read_rf(rtwdev, path, addr, mask); ++ mutex_unlock(&rtwdev->mutex); + + seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", + path, addr, mask, val); +@@ -141,6 +154,22 @@ static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v) + return 0; + } + ++static int rtw_debugfs_get_fix_rate(struct seq_file *m, void *v) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 fix_rate = dm_info->fix_rate; ++ ++ if (fix_rate >= DESC_RATE_MAX) { ++ seq_printf(m, "Fix rate disabled, fix_rate = %u\n", fix_rate); ++ return 0; ++ } ++ ++ seq_printf(m, "Data frames fixed at desc rate %u\n", fix_rate); ++ return 0; ++} ++ + static int rtw_debugfs_copy_from_user(char tmp[], int size, + const char __user *buffer, size_t count, + int num) +@@ -154,8 +183,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size, + + tmp_len = (count > size - 1 ? size - 1 : count); + +- if (!buffer || copy_from_user(tmp, buffer, tmp_len)) +- return count; ++ if (copy_from_user(tmp, buffer, tmp_len)) ++ return -EFAULT; + + tmp[tmp_len] = '\0'; + +@@ -172,13 +201,16 @@ static ssize_t rtw_debugfs_set_read_reg(struct file *filp, + char tmp[32 + 1]; + u32 addr, len; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); ++ if (ret) ++ return ret; + + num = sscanf(tmp, "%x %x", &addr, &len); + + if (num != 2) +- return count; ++ return -EINVAL; + + if (len != 1 && len != 2 && len != 4) { + rtw_warn(rtwdev, "read reg setting wrong len\n"); +@@ -242,11 +274,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) + for (i = 0 ; i < buf_size ; i += 8) { + if (i % page_size == 0) + seq_printf(m, "PAGE %d\n", (i + offset) / page_size); +- seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", +- *(buf + i), *(buf + i + 1), +- *(buf + i + 2), *(buf + i + 3), +- *(buf + i + 4), *(buf + i + 5), +- *(buf + i + 6), *(buf + i + 7)); ++ seq_printf(m, "%8ph\n", buf + i); + } + vfree(buf); + +@@ -263,8 +291,11 @@ static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp, + char tmp[32 + 1]; + u32 offset, page_num; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); ++ if (ret) ++ return ret; + + num = sscanf(tmp, "%d %d", &offset, &page_num); + +@@ -289,8 +320,11 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp, + char tmp[32 + 1]; + u32 input; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ if (ret) ++ return ret; + + num = kstrtoint(tmp, 0, &input); + +@@ -313,14 +347,17 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp, + char tmp[32 + 1]; + u32 addr, val, len; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ if (ret) ++ return ret; + + /* write BB/MAC register */ + num = sscanf(tmp, "%x %x %x", &addr, &val, &len); + + if (num != 3) +- return count; ++ return -EINVAL; + + switch (len) { + case 1: +@@ -356,18 +393,23 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp, + char tmp[32 + 1]; + u8 param[8]; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ if (ret) ++ return ret; + + num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx", + ¶m[0], ¶m[1], ¶m[2], ¶m[3], + ¶m[4], ¶m[5], ¶m[6], ¶m[7]); + if (num != 8) { +- rtw_info(rtwdev, "invalid H2C command format for debug\n"); ++ rtw_warn(rtwdev, "invalid H2C command format for debug\n"); + return -EINVAL; + } + ++ mutex_lock(&rtwdev->mutex); + rtw_fw_h2c_cmd_dbg(rtwdev, param); ++ mutex_unlock(&rtwdev->mutex); + + return count; + } +@@ -381,17 +423,22 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp, + char tmp[32 + 1]; + u32 path, addr, mask, val; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); ++ if (ret) ++ return ret; + + num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val); + + if (num != 4) { + rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); +- return count; ++ return -EINVAL; + } + ++ mutex_lock(&rtwdev->mutex); + rtw_write_rf(rtwdev, path, addr, mask, val); ++ mutex_unlock(&rtwdev->mutex); + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", + path, addr, mask, val); +@@ -409,14 +456,17 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp, + char tmp[32 + 1]; + u32 path, addr, mask; + int num; ++ int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); ++ if (ret) ++ return ret; + + num = sscanf(tmp, "%x %x %x", &path, &addr, &mask); + + if (num != 3) { + rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); +- return count; ++ return -EINVAL; + } + + debugfs_priv->rf_path = path; +@@ -426,6 +476,33 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp, + return count; + } + ++static ssize_t rtw_debugfs_set_fix_rate(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *loff) ++{ ++ struct seq_file *seqpriv = (struct seq_file *)filp->private_data; ++ struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 fix_rate; ++ char tmp[32 + 1]; ++ int ret; ++ ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ if (ret) ++ return ret; ++ ++ ret = kstrtou8(tmp, 0, &fix_rate); ++ if (ret) { ++ rtw_warn(rtwdev, "invalid args, [rate]\n"); ++ return ret; ++ } ++ ++ dm_info->fix_rate = fix_rate; ++ ++ return count; ++} ++ + static int rtw_debug_get_mac_page(struct seq_file *m, void *v) + { + struct rtw_debugfs_priv *debugfs_priv = m->private; +@@ -471,6 +548,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) + u32 addr, offset, data; + u8 path; + ++ mutex_lock(&rtwdev->mutex); ++ + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { + seq_printf(m, "RF path:%d\n", path); + for (addr = 0; addr < 0x100; addr += 4) { +@@ -485,6 +564,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) + seq_puts(m, "\n"); + } + ++ mutex_unlock(&rtwdev->mutex); ++ + return 0; + } + +@@ -573,15 +654,19 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw_hal *hal = &rtwdev->hal; +- u8 path, rate; ++ u8 path, rate, bw, ch, regd; + struct rtw_power_params pwr_param = {0}; +- u8 bw = hal->current_band_width; +- u8 ch = hal->current_channel; +- u8 regd = rtwdev->regd.txpwr_regd; + ++ mutex_lock(&rtwdev->mutex); ++ bw = hal->current_band_width; ++ ch = hal->current_channel; ++ regd = rtw_regd_get(rtwdev); ++ ++ seq_printf(m, "channel: %u\n", ch); ++ seq_printf(m, "bandwidth: %u\n", bw); + seq_printf(m, "regulatory: %s\n", rtw_get_regd_string(regd)); +- seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", +- "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); ++ seq_printf(m, "%-4s %-10s %-9s %-9s (%-4s %-4s %-4s) %-4s\n", ++ "path", "rate", "pwr", "base", "byr", "lmt", "sar", "rem"); + + mutex_lock(&hal->tx_power_mutex); + for (path = RF_PATH_A; path <= RF_PATH_B; path++) { +@@ -603,22 +688,48 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) + + seq_printf(m, "%4c ", path + 'A'); + rtw_print_rate(m, rate); +- seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n", ++ seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d %4d) %4d\n", + hal->tx_pwr_tbl[path][rate], + hal->tx_pwr_tbl[path][rate], + pwr_param.pwr_base, +- min_t(s8, pwr_param.pwr_offset, +- pwr_param.pwr_limit), ++ min3(pwr_param.pwr_offset, ++ pwr_param.pwr_limit, ++ pwr_param.pwr_sar), + pwr_param.pwr_offset, pwr_param.pwr_limit, ++ pwr_param.pwr_sar, + pwr_param.pwr_remnant); + } + } + + mutex_unlock(&hal->tx_power_mutex); ++ mutex_unlock(&rtwdev->mutex); + + return 0; + } + ++void rtw_debugfs_get_simple_phy_info(struct seq_file *m) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_traffic_stats *stats = &rtwdev->stats; ++ ++ seq_printf(m, "%-40s = %ddBm/ %d\n", "RSSI/ STA Channel", ++ dm_info->rssi[RF_PATH_A] - 100, hal->current_channel); ++ ++ seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n", ++ stats->tx_throughput, stats->rx_throughput); ++ ++ seq_puts(m, "[Tx Rate] = "); ++ rtw_print_rate(m, dm_info->tx_rate); ++ seq_printf(m, "(0x%x)\n", dm_info->tx_rate); ++ ++ seq_puts(m, "[Rx Rate] = "); ++ rtw_print_rate(m, dm_info->curr_rx_rate); ++ seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate); ++} ++ + static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v) + { + struct rtw_debugfs_priv *debugfs_priv = m->private; +@@ -636,8 +747,10 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v) + seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel); + seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width); + seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]); +- seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n", ++ seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n", + stats->tx_throughput, stats->rx_throughput); ++ seq_printf(m, "1SS for TX and RX = %c\n\n", rtwdev->hal.txrx_1ss ? ++ 'Y' : 'N'); + + seq_puts(m, "==========[Tx Phy Info]========\n"); + seq_puts(m, "[Tx Rate] = "); +@@ -751,7 +864,9 @@ static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v) + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + ++ mutex_lock(&rtwdev->mutex); + rtw_coex_display_coex_info(rtwdev, m); ++ mutex_unlock(&rtwdev->mutex); + + return 0; + } +@@ -768,7 +883,9 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp, + bool enable; + int ret; + +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ if (ret) ++ return ret; + + ret = kstrtobool(tmp, &enable); + if (ret) { +@@ -777,7 +894,7 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp, + } + + mutex_lock(&rtwdev->mutex); +- coex->stop_dm = enable == 0; ++ coex->manual_control = !enable; + mutex_unlock(&rtwdev->mutex); + + return count; +@@ -790,11 +907,201 @@ static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v) + struct rtw_coex *coex = &rtwdev->coex; + + seq_printf(m, "coex mechanism %s\n", +- coex->stop_dm ? "disabled" : "enabled"); ++ coex->manual_control ? "disabled" : "enabled"); + + return 0; + } + ++static ssize_t rtw_debugfs_set_edcca_enable(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *loff) ++{ ++ struct seq_file *seqpriv = (struct seq_file *)filp->private_data; ++ struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ bool input; ++ int err; ++ ++ err = kstrtobool_from_user(buffer, count, &input); ++ if (err) ++ return err; ++ ++ rtw_edcca_enabled = input; ++ rtw_phy_adaptivity_set_mode(rtwdev); ++ ++ return count; ++} ++ ++static int rtw_debugfs_get_edcca_enable(struct seq_file *m, void *v) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ seq_printf(m, "EDCCA %s: EDCCA mode %d\n", ++ rtw_edcca_enabled ? "enabled" : "disabled", ++ dm_info->edcca_mode); ++ return 0; ++} ++ ++static ssize_t rtw_debugfs_set_fw_crash(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *loff) ++{ ++ struct seq_file *seqpriv = (struct seq_file *)filp->private_data; ++ struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ char tmp[32 + 1]; ++ bool input; ++ int ret; ++ ++ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); ++ if (ret) ++ return ret; ++ ++ ret = kstrtobool(tmp, &input); ++ if (ret) ++ return -EINVAL; ++ ++ if (!input) ++ return -EINVAL; ++ ++ if (test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)) ++ return -EINPROGRESS; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_leave_lps_deep(rtwdev); ++ set_bit(RTW_FLAG_RESTART_TRIGGERING, rtwdev->flags); ++ rtw_write8(rtwdev, REG_HRCV_MSG, 1); ++ mutex_unlock(&rtwdev->mutex); ++ ++ return count; ++} ++ ++static int rtw_debugfs_get_fw_crash(struct seq_file *m, void *v) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ ++ seq_printf(m, "%d\n", ++ test_bit(RTW_FLAG_RESTART_TRIGGERING, rtwdev->flags) || ++ test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)); ++ return 0; ++} ++ ++static ssize_t rtw_debugfs_set_force_lowest_basic_rate(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *loff) ++{ ++ struct seq_file *seqpriv = (struct seq_file *)filp->private_data; ++ struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ bool input; ++ int err; ++ ++ err = kstrtobool_from_user(buffer, count, &input); ++ if (err) ++ return err; ++ ++ if (input) ++ set_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags); ++ else ++ clear_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags); ++ ++ return count; ++} ++ ++static int rtw_debugfs_get_force_lowest_basic_rate(struct seq_file *m, void *v) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ ++ seq_printf(m, "force lowest basic rate: %d\n", ++ test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags)); ++ ++ return 0; ++} ++ ++static ssize_t rtw_debugfs_set_dm_cap(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *loff) ++{ ++ struct seq_file *seqpriv = (struct seq_file *)filp->private_data; ++ struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ int bit; ++ bool en; ++ ++ if (kstrtoint_from_user(buffer, count, 10, &bit)) ++ return -EINVAL; ++ ++ en = bit > 0; ++ bit = abs(bit); ++ ++ if (bit >= RTW_DM_CAP_NUM) { ++ rtw_warn(rtwdev, "unknown DM CAP %d\n", bit); ++ return -EINVAL; ++ } ++ ++ if (en) ++ dm_info->dm_flags &= ~BIT(bit); ++ else ++ dm_info->dm_flags |= BIT(bit); ++ ++ debugfs_priv->dm_cap.bit = bit; ++ ++ return count; ++} ++ ++static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ int i, path; ++ u32 val; ++ ++ seq_printf(m, "\n(%2d) %c%s\n\n", RTW_DM_CAP_TXGAPK, ++ dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+', ++ rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]); ++ ++ mutex_lock(&rtwdev->mutex); ++ ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK); ++ seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val); ++ ++ for (i = 0; i < RF_HW_OFFSET_NUM; i++) ++ seq_printf(m, "[TXGAPK] offset %d %d\n", ++ txgapk->rf3f_fs[path][i], i); ++ seq_puts(m, "\n"); ++ } ++ mutex_unlock(&rtwdev->mutex); ++} ++ ++static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v) ++{ ++ struct rtw_debugfs_priv *debugfs_priv = m->private; ++ struct rtw_dev *rtwdev = debugfs_priv->rtwdev; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ int i; ++ ++ switch (debugfs_priv->dm_cap.bit) { ++ case RTW_DM_CAP_TXGAPK: ++ dump_gapk_status(rtwdev, m); ++ break; ++ default: ++ for (i = 1; i < RTW_DM_CAP_NUM; i++) { ++ seq_printf(m, "(%2d) %c%s\n", i, ++ dm_info->dm_flags & BIT(i) ? '-' : '+', ++ rtw_dm_cap_strs[i]); ++ } ++ break; ++ } ++ debugfs_priv->dm_cap.bit = RTW_DM_CAP_NA; ++ return 0; ++} ++ + #define rtw_debug_impl_mac(page, addr) \ + static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \ + .cb_read = rtw_debug_get_mac_page, \ +@@ -875,6 +1182,11 @@ static struct rtw_debugfs_priv rtw_debug_priv_read_reg = { + .cb_read = rtw_debugfs_get_read_reg, + }; + ++static struct rtw_debugfs_priv rtw_debug_priv_fix_rate = { ++ .cb_write = rtw_debugfs_set_fix_rate, ++ .cb_read = rtw_debugfs_get_fix_rate, ++}; ++ + static struct rtw_debugfs_priv rtw_debug_priv_dump_cam = { + .cb_write = rtw_debugfs_set_single_input, + .cb_read = rtw_debugfs_get_dump_cam, +@@ -898,12 +1210,32 @@ static struct rtw_debugfs_priv rtw_debug_priv_coex_info = { + .cb_read = rtw_debugfs_get_coex_info, + }; + ++static struct rtw_debugfs_priv rtw_debug_priv_edcca_enable = { ++ .cb_write = rtw_debugfs_set_edcca_enable, ++ .cb_read = rtw_debugfs_get_edcca_enable, ++}; ++ ++static struct rtw_debugfs_priv rtw_debug_priv_fw_crash = { ++ .cb_write = rtw_debugfs_set_fw_crash, ++ .cb_read = rtw_debugfs_get_fw_crash, ++}; ++ ++static struct rtw_debugfs_priv rtw_debug_priv_force_lowest_basic_rate = { ++ .cb_write = rtw_debugfs_set_force_lowest_basic_rate, ++ .cb_read = rtw_debugfs_get_force_lowest_basic_rate, ++}; ++ ++static struct rtw_debugfs_priv rtw_debug_priv_dm_cap = { ++ .cb_write = rtw_debugfs_set_dm_cap, ++ .cb_read = rtw_debugfs_get_dm_cap, ++}; ++ + #define rtw_debugfs_add_core(name, mode, fopname, parent) \ + do { \ + rtw_debug_priv_ ##name.rtwdev = rtwdev; \ +- if (!debugfs_create_file(#name, mode, \ ++ if (IS_ERR(debugfs_create_file(#name, mode, \ + parent, &rtw_debug_priv_ ##name,\ +- &file_ops_ ##fopname)) \ ++ &file_ops_ ##fopname))) \ + pr_debug("Unable to initialize debugfs:%s\n", \ + #name); \ + } while (0) +@@ -925,6 +1257,7 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev) + rtw_debugfs_add_rw(read_reg); + rtw_debugfs_add_w(rf_write); + rtw_debugfs_add_rw(rf_read); ++ rtw_debugfs_add_rw(fix_rate); + rtw_debugfs_add_rw(dump_cam); + rtw_debugfs_add_rw(rsvd_page); + rtw_debugfs_add_r(phy_info); +@@ -971,6 +1304,10 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev) + } + rtw_debugfs_add_r(rf_dump); + rtw_debugfs_add_r(tx_pwr_tbl); ++ rtw_debugfs_add_rw(edcca_enable); ++ rtw_debugfs_add_rw(fw_crash); ++ rtw_debugfs_add_rw(force_lowest_basic_rate); ++ rtw_debugfs_add_rw(dm_cap); + } + + #endif /* CONFIG_RTW88_DEBUGFS */ +diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h +index a0f36f29b4a6..a9149c6c2b48 100644 +--- a/drivers/net/wireless/realtek/rtw88/debug.h ++++ b/drivers/net/wireless/realtek/rtw88/debug.h +@@ -19,6 +19,12 @@ enum rtw_debug_mask { + RTW_DBG_PS = 0x00000400, + RTW_DBG_BF = 0x00000800, + RTW_DBG_WOW = 0x00001000, ++ RTW_DBG_CFO = 0x00002000, ++ RTW_DBG_PATH_DIV = 0x00004000, ++ RTW_DBG_ADAPTIVITY = 0x00008000, ++ RTW_DBG_HW_SCAN = 0x00010000, ++ RTW_DBG_STATE = 0x00020000, ++ RTW_DBG_SDIO = 0x00040000, + + RTW_DBG_ALL = 0xffffffff + }; +@@ -26,6 +32,7 @@ enum rtw_debug_mask { + #ifdef CONFIG_RTW88_DEBUGFS + + void rtw_debugfs_init(struct rtw_dev *rtwdev); ++void rtw_debugfs_get_simple_phy_info(struct seq_file *m); + + #else + +diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c +index c266c84ef233..b85075cd68d0 100644 +--- a/drivers/net/wireless/realtek/rtw88/efuse.c ++++ b/drivers/net/wireless/realtek/rtw88/efuse.c +@@ -86,7 +86,7 @@ static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map, + + static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u32 size = rtwdev->efuse.physical_size; + u32 efuse_ctl; + u32 addr; +@@ -145,7 +145,7 @@ EXPORT_SYMBOL(rtw_read8_physical_efuse); + + int rtw_parse_efuse_map(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + u32 phy_size = efuse->physical_size; + u32 log_size = efuse->logical_size; +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index 40bcfabd2d21..071e8ec2f879 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -13,6 +13,9 @@ + #include "debug.h" + #include "util.h" + #include "wow.h" ++#include "ps.h" ++#include "phy.h" ++#include "mac.h" + + static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, + struct sk_buff *skb) +@@ -27,6 +30,12 @@ static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, + case C2H_CCX_RPT: + rtw_tx_report_handle(rtwdev, skb, C2H_CCX_RPT); + break; ++ case C2H_SCAN_STATUS_RPT: ++ rtw_hw_scan_status_report(rtwdev, skb); ++ break; ++ case C2H_CHAN_SWITCH: ++ rtw_hw_scan_chan_switch(rtwdev, skb); ++ break; + default: + break; + } +@@ -109,7 +118,11 @@ static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta) + si->ra_report.desc_rate = rate; + si->ra_report.bit_rate = bit_rate; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(bit_rate); ++#else + sta->max_rc_amsdu_len = get_max_amsdu_len(bit_rate); ++#endif + } + + static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload, +@@ -126,6 +139,84 @@ static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload, + rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data); + } + ++struct rtw_beacon_filter_iter_data { ++ struct rtw_dev *rtwdev; ++ u8 *payload; ++}; ++ ++static void rtw_fw_bcn_filter_notify_vif_iter(void *data, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw_beacon_filter_iter_data *iter_data = data; ++ struct rtw_dev *rtwdev = iter_data->rtwdev; ++ u8 *payload = iter_data->payload; ++ u8 type = GET_BCN_FILTER_NOTIFY_TYPE(payload); ++ u8 event = GET_BCN_FILTER_NOTIFY_EVENT(payload); ++ s8 sig = (s8)GET_BCN_FILTER_NOTIFY_RSSI(payload); ++ ++ switch (type) { ++ case BCN_FILTER_NOTIFY_SIGNAL_CHANGE: ++ event = event ? NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH : ++ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; ++ ieee80211_cqm_rssi_notify(vif, event, sig, GFP_KERNEL); ++ break; ++ case BCN_FILTER_CONNECTION_LOSS: ++ ieee80211_connection_loss(vif); ++ break; ++ case BCN_FILTER_CONNECTED: ++ rtwdev->beacon_loss = false; ++ break; ++ case BCN_FILTER_NOTIFY_BEACON_LOSS: ++ rtwdev->beacon_loss = true; ++ rtw_leave_lps(rtwdev); ++ break; ++ } ++} ++ ++static void rtw_fw_bcn_filter_notify(struct rtw_dev *rtwdev, u8 *payload, ++ u8 length) ++{ ++ struct rtw_beacon_filter_iter_data dev_iter_data; ++ ++ dev_iter_data.rtwdev = rtwdev; ++ dev_iter_data.payload = payload; ++ rtw_iterate_vifs(rtwdev, rtw_fw_bcn_filter_notify_vif_iter, ++ &dev_iter_data); ++} ++ ++static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload, ++ u8 length) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ dm_info->scan_density = payload[0]; ++ ++ rtw_dbg(rtwdev, RTW_DBG_FW, "scan.density = %x\n", ++ dm_info->scan_density); ++} ++ ++static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload, ++ u8 length) ++{ ++ struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; ++ struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload; ++ ++ rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, ++ "Adaptivity: density %x igi %x l2h_th_init %x l2h %x h2l %x option %x\n", ++ result->density, result->igi, result->l2h_th_init, result->l2h, ++ result->h2l, result->option); ++ ++ rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "Reg Setting: L2H %x H2L %x\n", ++ rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, ++ edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask), ++ rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr, ++ edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask)); ++ ++ rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "EDCCA Flag %s\n", ++ rtw_read32_mask(rtwdev, REG_EDCCA_REPORT, BIT_EDCCA_FLAG) ? ++ "Set" : "Unset"); ++} ++ + void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) + { + struct rtw_c2h_cmd *c2h; +@@ -148,9 +239,15 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) + case C2H_BT_INFO: + rtw_coex_bt_info_notify(rtwdev, c2h->payload, len); + break; ++ case C2H_BT_HID_INFO: ++ rtw_coex_bt_hid_info_notify(rtwdev, c2h->payload, len); ++ break; + case C2H_WLAN_INFO: + rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len); + break; ++ case C2H_BCN_FILTER_NOTIFY: ++ rtw_fw_bcn_filter_notify(rtwdev, c2h->payload, len); ++ break; + case C2H_HALMAC: + rtw_fw_c2h_cmd_handle_ext(rtwdev, skb); + break; +@@ -183,6 +280,19 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, + case C2H_BT_MP_INFO: + rtw_coex_info_response(rtwdev, skb); + break; ++ case C2H_WLAN_RFON: ++ complete(&rtwdev->lps_leave_check); ++ dev_kfree_skb_any(skb); ++ break; ++ case C2H_SCAN_RESULT: ++ complete(&rtwdev->fw_scan_density); ++ rtw_fw_scan_result(rtwdev, c2h->payload, len); ++ dev_kfree_skb_any(skb); ++ break; ++ case C2H_ADAPTIVITY: ++ rtw_fw_adaptivity_result(rtwdev, c2h->payload, len); ++ dev_kfree_skb_any(skb); ++ break; + default: + /* pass offset for further operation */ + *((u32 *)skb->cb) = pkt_offset; +@@ -202,13 +312,64 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev) + } + EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr); + ++static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev, ++ struct rtw_h2c_register *h2c) ++{ ++ u32 box_reg, box_ex_reg; ++ u8 box_state, box; ++ int ret; ++ ++ rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0, ++ h2c->w1); ++ ++ lockdep_assert_held(&rtwdev->mutex); ++ ++ box = rtwdev->h2c.last_box_num; ++ switch (box) { ++ case 0: ++ box_reg = REG_HMEBOX0; ++ box_ex_reg = REG_HMEBOX0_EX; ++ break; ++ case 1: ++ box_reg = REG_HMEBOX1; ++ box_ex_reg = REG_HMEBOX1_EX; ++ break; ++ case 2: ++ box_reg = REG_HMEBOX2; ++ box_ex_reg = REG_HMEBOX2_EX; ++ break; ++ case 3: ++ box_reg = REG_HMEBOX3; ++ box_ex_reg = REG_HMEBOX3_EX; ++ break; ++ default: ++ WARN(1, "invalid h2c mail box number\n"); ++ return; ++ } ++ ++ ret = read_poll_timeout_atomic(rtw_read8, box_state, ++ !((box_state >> box) & 0x1), 100, 3000, ++ false, rtwdev, REG_HMETFR); ++ ++ if (ret) { ++ rtw_err(rtwdev, "failed to send h2c command\n"); ++ return; ++ } ++ ++ rtw_write32(rtwdev, box_ex_reg, h2c->w1); ++ rtw_write32(rtwdev, box_reg, h2c->w0); ++ ++ if (++rtwdev->h2c.last_box_num >= 4) ++ rtwdev->h2c.last_box_num = 0; ++} ++ + static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, + u8 *h2c) + { ++ struct rtw_h2c_cmd *h2c_cmd = (struct rtw_h2c_cmd *)h2c; + u8 box; + u8 box_state; + u32 box_reg, box_ex_reg; +- int idx; + int ret; + + rtw_dbg(rtwdev, RTW_DBG_FW, +@@ -216,7 +377,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, + h2c[3], h2c[2], h2c[1], h2c[0], + h2c[7], h2c[6], h2c[5], h2c[4]); + +- spin_lock(&rtwdev->h2c.lock); ++ lockdep_assert_held(&rtwdev->mutex); + + box = rtwdev->h2c.last_box_num; + switch (box) { +@@ -238,7 +399,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, + break; + default: + WARN(1, "invalid h2c mail box number\n"); +- goto out; ++ return; + } + + ret = read_poll_timeout_atomic(rtw_read8, box_state, +@@ -247,19 +408,14 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, + + if (ret) { + rtw_err(rtwdev, "failed to send h2c command\n"); +- goto out; ++ return; + } + +- for (idx = 0; idx < 4; idx++) +- rtw_write8(rtwdev, box_reg + idx, h2c[idx]); +- for (idx = 0; idx < 4; idx++) +- rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]); ++ rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext)); ++ rtw_write32(rtwdev, box_reg, le32_to_cpu(h2c_cmd->msg)); + + if (++rtwdev->h2c.last_box_num >= 4) + rtwdev->h2c.last_box_num = 0; +- +-out: +- spin_unlock(&rtwdev->h2c.lock); + } + + void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c) +@@ -271,15 +427,13 @@ static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt) + { + int ret; + +- spin_lock(&rtwdev->h2c.lock); ++ lockdep_assert_held(&rtwdev->mutex); + + FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq); + ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE); + if (ret) + rtw_err(rtwdev, "failed to send h2c packet\n"); + rtwdev->h2c.seq++; +- +- spin_unlock(&rtwdev->h2c.lock); + } + + void +@@ -346,6 +500,18 @@ void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para) + } + EXPORT_SYMBOL(rtw_fw_do_iqk); + ++void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start) ++{ ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WIFI_CALIBRATION); ++ ++ RFK_SET_INFORM_START(h2c_pkt, start); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++EXPORT_SYMBOL(rtw_fw_inform_rfk_status); ++ + void rtw_fw_query_bt_info(struct rtw_dev *rtwdev) + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; +@@ -357,6 +523,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev) + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + ++void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) ++{ ++ struct rtw_h2c_register h2c = {}; ++ ++ if (rtwvif->net_type != RTW_NET_MGD_LINKED) ++ return; ++ ++ /* Leave LPS before default port H2C so FW timer is correct */ ++ rtw_leave_lps(rtwdev); ++ ++ h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) | ++ u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) | ++ u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID); ++ ++ rtw_fw_send_h2c_command_register(rtwdev, &h2c); ++} ++ + void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw) + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; +@@ -425,6 +608,18 @@ void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev, + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + ++void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data) ++{ ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_HID_INFO); ++ ++ SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, sub_id); ++ SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, data); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ + void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data) + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; +@@ -457,11 +652,18 @@ void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, ++ bool reset_ra_mask) ++#else + void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) ++#endif + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; +- bool no_update = si->updated; + bool disable_pt = true; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) ++ bool reset_ra_mask = true; ++#endif + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO); + +@@ -471,7 +673,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable); + SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode); + SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en); +- SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update); ++ SET_RA_INFO_NO_UPDATE(h2c_pkt, !reset_ra_mask); + SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable); + SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt); + SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff)); +@@ -480,7 +682,6 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24); + + si->init_ra_lv = 0; +- si->updated = true; + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } +@@ -496,6 +697,64 @@ void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect) + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + ++void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev) ++{ ++ struct rtw_traffic_stats *stats = &rtwdev->stats; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_PHY_INFO); ++ SET_WL_PHY_INFO_TX_TP(h2c_pkt, stats->tx_throughput); ++ SET_WL_PHY_INFO_RX_TP(h2c_pkt, stats->rx_throughput); ++ SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, dm_info->tx_rate); ++ SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, dm_info->curr_rx_rate); ++ SET_WL_PHY_INFO_RX_EVM(h2c_pkt, dm_info->rx_evm_dbm[RF_PATH_A]); ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ ++void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect, ++ struct ieee80211_vif *vif) ++{ ++ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; ++ struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); ++ static const u8 rssi_min = 0, rssi_max = 100, rssi_offset = 100; ++ struct rtw_sta_info *si = ++ sta ? (struct rtw_sta_info *)sta->drv_priv : NULL; ++ s32 threshold = bss_conf->cqm_rssi_thold + rssi_offset; ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER)) ++ return; ++ ++ if (!connect) { ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1); ++ SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect); ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++ ++ return; ++ } ++ ++ if (!si) ++ return; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P0); ++ ether_addr_copy(&h2c_pkt[1], bss_conf->bssid); ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++ ++ memset(h2c_pkt, 0, sizeof(h2c_pkt)); ++ threshold = clamp_t(s32, threshold, rssi_min, rssi_max); ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1); ++ SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect); ++ SET_BCN_FILTER_OFFLOAD_P1_OFFLOAD_MODE(h2c_pkt, ++ BCN_FILTER_OFFLOAD_MODE_DEFAULT); ++ SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, (u8)threshold); ++ SET_BCN_FILTER_OFFLOAD_P1_BCN_LOSS_CNT(h2c_pkt, BCN_LOSS_CNT); ++ SET_BCN_FILTER_OFFLOAD_P1_MACID(h2c_pkt, si->mac_id); ++ SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, bss_conf->cqm_rssi_hyst); ++ SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, bss_conf->beacon_int); ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ + void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev) + { + struct rtw_lps_conf *conf = &rtwdev->lps_conf; +@@ -628,7 +887,7 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable) + + SET_NLO_FUN_EN(h2c_pkt, enable); + if (enable) { +- if (rtw_fw_lps_deep_mode) ++ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE) + SET_NLO_PS_32K(h2c_pkt, enable); + SET_NLO_IGNORE_SECURITY(h2c_pkt, enable); + SET_NLO_LOC_NLO_INFO(h2c_pkt, loc_nlo); +@@ -637,6 +896,16 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable) + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + ++void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev) ++{ ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RECOVER_BT_DEV); ++ SET_RECOVER_BT_DEV_EN(h2c_pkt, 1); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ + void rtw_fw_set_pg_info(struct rtw_dev *rtwdev) + { + struct rtw_lps_conf *conf = &rtwdev->lps_conf; +@@ -719,7 +988,7 @@ void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev) + static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req; + struct rtw_nlo_info_hdr *nlo_hdr; + struct cfg80211_ssid *ssid; +@@ -774,7 +1043,7 @@ static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) + static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req; + struct ieee80211_channel *channels = pno_req->channels; + struct sk_buff *skb; +@@ -808,7 +1077,7 @@ static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw) + static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info; + struct rtw_lps_pg_dpk_hdr *dpk_hdr; + struct sk_buff *skb; +@@ -833,7 +1102,7 @@ static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw) + static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + struct rtw_lps_pg_info_hdr *pg_info_hdr; + struct rtw_wow_param *rtw_wow = &rtwdev->wow; +@@ -866,6 +1135,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + struct rtw_vif *rtwvif; + struct sk_buff *skb_new; + struct cfg80211_ssid *ssid; ++ u16 tim_offset = 0; + + if (rsvd_pkt->type == RSVD_DUMMY) { + skb_new = alloc_skb(1, GFP_KERNEL); +@@ -884,7 +1154,12 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + + switch (rsvd_pkt->type) { + case RSVD_BEACON: +- skb_new = ieee80211_beacon_get(hw, vif); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL, 0); ++#else ++ skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL); ++#endif ++ rsvd_pkt->tim_offset = tim_offset; + break; + case RSVD_PS_POLL: + skb_new = ieee80211_pspoll_get(hw, vif); +@@ -893,10 +1168,26 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + skb_new = ieee80211_proberesp_get(hw, vif); + break; + case RSVD_NULL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 17) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ skb_new = ieee80211_nullfunc_get(hw, vif, -1, false); ++#else + skb_new = ieee80211_nullfunc_get(hw, vif, false); ++#endif ++#else ++ skb_new = ieee80211_nullfunc_get(hw, vif); ++#endif + break; + case RSVD_QOS_NULL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 17) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ skb_new = ieee80211_nullfunc_get(hw, vif, -1, true); ++#else + skb_new = ieee80211_nullfunc_get(hw, vif, true); ++#endif ++#else ++ skb_new = ieee80211_nullfunc_get(hw, vif); ++#endif + break; + case RSVD_LPS_PG_DPK: + skb_new = rtw_lps_pg_dpk_get(hw); +@@ -935,7 +1226,7 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, + enum rtw_rsvd_packet_type type) + { + struct rtw_tx_pkt_info pkt_info = {0}; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 *pkt_desc; + + rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type); +@@ -1201,6 +1492,10 @@ static void rtw_build_rsvd_page_iter(void *data, u8 *mac, + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct rtw_rsvd_page *rsvd_pkt; + ++ /* AP not yet started, don't gather its rsvd pages */ ++ if (vif->type == NL80211_IFTYPE_AP && !rtwdev->ap_active) ++ return; ++ + list_for_each_entry(rsvd_pkt, &rtwvif->rsvd_page_list, vif_list) { + if (rsvd_pkt->type == RSVD_BEACON) + list_add(&rsvd_pkt->build_list, +@@ -1246,7 +1541,7 @@ static int __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev) + static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size) + { + struct ieee80211_hw *hw = rtwdev->hw; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *iter; + struct rtw_rsvd_page *rsvd_pkt; + u32 page = 0; +@@ -1415,6 +1710,17 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev) + return ret; + } + ++void rtw_fw_update_beacon_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ++ update_beacon_work); ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_fw_download_rsvd_page(rtwdev); ++ rtw_send_rsvd_page_h2c(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++} ++ + static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, + u32 *buf, u32 residue, u16 start_pg) + { +@@ -1450,7 +1756,7 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, + static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel, + u32 offset, u32 size, u32 *buf) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u32 start_pg, residue; + + if (sel >= RTW_FW_FIFO_MAX) { +@@ -1474,7 +1780,7 @@ static bool rtw_fw_dump_check_size(struct rtw_dev *rtwdev, + case RTW_FW_FIFO_SEL_RX: + if ((start_addr + size) > rtwdev->chip->fw_fifo_addr[sel]) + return false; +- /*fall through*/ ++ fallthrough; + default: + return true; + } +@@ -1509,7 +1815,7 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, + static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size, + u8 location) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN; + +@@ -1585,3 +1891,496 @@ void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable) + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); + } ++ ++void rtw_fw_adaptivity(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ if (!rtw_edcca_enabled) { ++ dm_info->edcca_mode = RTW_EDCCA_NORMAL; ++ rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, ++ "EDCCA disabled by debugfs\n"); ++ } ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY); ++ SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode); ++ SET_ADAPTIVITY_OPTION(h2c_pkt, 1); ++ SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]); ++ SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini); ++ SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ ++void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start) ++{ ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SCAN); ++ SET_SCAN_START(h2c_pkt, start); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++} ++ ++static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb, ++ struct sk_buff_head *list, u8 *bands, ++ struct rtw_vif *rtwvif) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct ieee80211_scan_ies *ies = rtwvif->scan_ies; ++ struct sk_buff *new; ++ u8 idx; ++ ++ for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) { ++ if (!(BIT(idx) & chip->band)) ++ continue; ++ new = skb_copy(skb, GFP_KERNEL); ++ if (!new) ++ return -ENOMEM; ++ skb_put_data(new, ies->ies[idx], ies->len[idx]); ++ skb_put_data(new, ies->common_ies, ies->common_ie_len); ++ skb_queue_tail(list, new); ++ (*bands)++; ++ } ++ ++ return 0; ++} ++ ++static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes, ++ struct sk_buff_head *probe_req_list) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct sk_buff *skb, *tmp; ++ u8 page_offset = 1, *buf, page_size = chip->page_size; ++ u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc; ++ u16 buf_offset = page_size * page_offset; ++ u8 tx_desc_sz = chip->tx_pkt_desc_sz; ++ u8 page_cnt, pages; ++ unsigned int pkt_len; ++ int ret; ++ ++ if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM)) ++ page_cnt = RTW_OLD_PROBE_PG_CNT; ++ else ++ page_cnt = RTW_PROBE_PG_CNT; ++ ++ pages = page_offset + num_probes * page_cnt; ++ ++ buf = kzalloc(page_size * pages, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ buf_offset -= tx_desc_sz; ++ skb_queue_walk_safe(probe_req_list, skb, tmp) { ++ skb_unlink(skb, probe_req_list); ++ rtw_fill_rsvd_page_desc(rtwdev, skb, RSVD_PROBE_REQ); ++ if (skb->len > page_size * page_cnt) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ memcpy(buf + buf_offset, skb->data, skb->len); ++ pkt_len = skb->len - tx_desc_sz; ++ loc = pg_addr - rtwdev->fifo.rsvd_boundary + page_offset; ++ __rtw_fw_update_pkt(rtwdev, RTW_PACKET_PROBE_REQ, pkt_len, loc); ++ ++ buf_offset += page_cnt * page_size; ++ page_offset += page_cnt; ++ kfree_skb(skb); ++ } ++ ++ ret = rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, buf_offset); ++ if (ret) { ++ rtw_err(rtwdev, "Download probe request to firmware failed\n"); ++ goto out; ++ } ++ ++ rtwdev->scan_info.probe_pg_size = page_offset; ++out: ++ kfree(buf); ++ skb_queue_walk_safe(probe_req_list, skb, tmp) ++ kfree_skb(skb); ++ ++ return ret; ++} ++ ++static int rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, ++ struct rtw_vif *rtwvif) ++{ ++ struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct sk_buff_head list; ++ struct sk_buff *skb, *tmp; ++ u8 num = req->n_ssids, i, bands = 0; ++ int ret; ++ ++ skb_queue_head_init(&list); ++ for (i = 0; i < num; i++) { ++ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, ++ req->ssids[i].ssid, ++ req->ssids[i].ssid_len, ++ req->ie_len); ++ if (!skb) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ret = rtw_append_probe_req_ie(rtwdev, skb, &list, &bands, ++ rtwvif); ++ if (ret) ++ goto out; ++ ++ kfree_skb(skb); ++ } ++ ++ return _rtw_hw_scan_update_probe_req(rtwdev, num * bands, &list); ++ ++out: ++ skb_queue_walk_safe(&list, skb, tmp) ++ kfree_skb(skb); ++ ++ return ret; ++} ++ ++static int rtw_add_chan_info(struct rtw_dev *rtwdev, struct rtw_chan_info *info, ++ struct rtw_chan_list *list, u8 *buf) ++{ ++ u8 *chan = &buf[list->size]; ++ u8 info_size = RTW_CH_INFO_SIZE; ++ ++ if (list->size > list->buf_size) ++ return -ENOMEM; ++ ++ CH_INFO_SET_CH(chan, info->channel); ++ CH_INFO_SET_PRI_CH_IDX(chan, info->pri_ch_idx); ++ CH_INFO_SET_BW(chan, info->bw); ++ CH_INFO_SET_TIMEOUT(chan, info->timeout); ++ CH_INFO_SET_ACTION_ID(chan, info->action_id); ++ CH_INFO_SET_EXTRA_INFO(chan, info->extra_info); ++ if (info->extra_info) { ++ EXTRA_CH_INFO_SET_ID(chan, RTW_SCAN_EXTRA_ID_DFS); ++ EXTRA_CH_INFO_SET_INFO(chan, RTW_SCAN_EXTRA_ACTION_SCAN); ++ EXTRA_CH_INFO_SET_SIZE(chan, RTW_EX_CH_INFO_SIZE - ++ RTW_EX_CH_INFO_HDR_SIZE); ++ EXTRA_CH_INFO_SET_DFS_EXT_TIME(chan, RTW_DFS_CHAN_TIME); ++ info_size += RTW_EX_CH_INFO_SIZE; ++ } ++ list->size += info_size; ++ list->ch_num++; ++ ++ return 0; ++} ++ ++static int rtw_add_chan_list(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ++ struct rtw_chan_list *list, u8 *buf) ++{ ++ struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct rtw_fifo_conf *fifo = &rtwdev->fifo; ++ struct ieee80211_channel *channel; ++ int i, ret = 0; ++ ++ for (i = 0; i < req->n_channels; i++) { ++ struct rtw_chan_info ch_info = {0}; ++ ++ channel = req->channels[i]; ++ ch_info.channel = channel->hw_value; ++ ch_info.bw = RTW_SCAN_WIDTH; ++ ch_info.pri_ch_idx = RTW_PRI_CH_IDX; ++ ch_info.timeout = req->duration_mandatory ? ++ req->duration : RTW_CHANNEL_TIME; ++ ++ if (channel->flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)) { ++ ch_info.action_id = RTW_CHANNEL_RADAR; ++ ch_info.extra_info = 1; ++ /* Overwrite duration for passive scans if necessary */ ++ ch_info.timeout = ch_info.timeout > RTW_PASS_CHAN_TIME ? ++ ch_info.timeout : RTW_PASS_CHAN_TIME; ++ } else { ++ ch_info.action_id = RTW_CHANNEL_ACTIVE; ++ } ++ ++ ret = rtw_add_chan_info(rtwdev, &ch_info, list, buf); ++ if (ret) ++ return ret; ++ } ++ ++ if (list->size > fifo->rsvd_pg_num << TX_PAGE_SIZE_SHIFT) { ++ rtw_err(rtwdev, "List exceeds rsvd page total size\n"); ++ return -EINVAL; ++ } ++ ++ list->addr = fifo->rsvd_h2c_info_addr + rtwdev->scan_info.probe_pg_size; ++ ret = rtw_fw_write_data_rsvd_page(rtwdev, list->addr, buf, list->size); ++ if (ret) ++ rtw_err(rtwdev, "Download channel list failed\n"); ++ ++ return ret; ++} ++ ++static void rtw_fw_set_scan_offload(struct rtw_dev *rtwdev, ++ struct rtw_ch_switch_option *opt, ++ struct rtw_vif *rtwvif, ++ struct rtw_chan_list *list) ++{ ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct rtw_fifo_conf *fifo = &rtwdev->fifo; ++ /* reserve one dummy page at the beginning for tx descriptor */ ++ u8 pkt_loc = fifo->rsvd_h2c_info_addr - fifo->rsvd_boundary + 1; ++ bool random_seq = req->flags & NL80211_SCAN_FLAG_RANDOM_SN; ++ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; ++ ++ rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_SCAN_OFFLOAD); ++ SET_PKT_H2C_TOTAL_LEN(h2c_pkt, H2C_PKT_CH_SWITCH_LEN); ++ ++ SCAN_OFFLOAD_SET_START(h2c_pkt, opt->switch_en); ++ SCAN_OFFLOAD_SET_BACK_OP_EN(h2c_pkt, opt->back_op_en); ++ SCAN_OFFLOAD_SET_RANDOM_SEQ_EN(h2c_pkt, random_seq); ++ SCAN_OFFLOAD_SET_NO_CCK_EN(h2c_pkt, req->no_cck); ++ SCAN_OFFLOAD_SET_CH_NUM(h2c_pkt, list->ch_num); ++ SCAN_OFFLOAD_SET_CH_INFO_SIZE(h2c_pkt, list->size); ++ SCAN_OFFLOAD_SET_CH_INFO_LOC(h2c_pkt, list->addr - fifo->rsvd_boundary); ++ SCAN_OFFLOAD_SET_OP_CH(h2c_pkt, scan_info->op_chan); ++ SCAN_OFFLOAD_SET_OP_PRI_CH_IDX(h2c_pkt, scan_info->op_pri_ch_idx); ++ SCAN_OFFLOAD_SET_OP_BW(h2c_pkt, scan_info->op_bw); ++ SCAN_OFFLOAD_SET_OP_PORT_ID(h2c_pkt, rtwvif->port); ++ SCAN_OFFLOAD_SET_OP_DWELL_TIME(h2c_pkt, req->duration_mandatory ? ++ req->duration : RTW_CHANNEL_TIME); ++ SCAN_OFFLOAD_SET_OP_GAP_TIME(h2c_pkt, RTW_OFF_CHAN_TIME); ++ SCAN_OFFLOAD_SET_SSID_NUM(h2c_pkt, req->n_ssids); ++ SCAN_OFFLOAD_SET_PKT_LOC(h2c_pkt, pkt_loc); ++ ++ rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); ++} ++ ++void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ struct ieee80211_scan_request *scan_req) ++{ ++ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; ++ struct cfg80211_scan_request *req = &scan_req->req; ++ u8 mac_addr[ETH_ALEN]; ++ ++ rtwdev->scan_info.scanning_vif = vif; ++ rtwvif->scan_ies = &scan_req->ies; ++ rtwvif->scan_req = req; ++ ++ ieee80211_stop_queues(rtwdev->hw); ++ rtw_leave_lps_deep(rtwdev); ++ rtw_hci_flush_all_queues(rtwdev, false); ++ rtw_mac_flush_all_queues(rtwdev, false); ++ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) ++ get_random_mask_addr(mac_addr, req->mac_addr, ++ req->mac_addr_mask); ++ else ++ ether_addr_copy(mac_addr, vif->addr); ++ ++ rtw_core_scan_start(rtwdev, rtwvif, mac_addr, true); ++ ++ rtwdev->hal.rcr &= ~BIT_CBSSID_BCN; ++ rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); ++} ++ ++void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool aborted) ++{ ++ struct cfg80211_scan_info info = { ++ .aborted = aborted, ++ }; ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_vif *rtwvif; ++ u8 chan = scan_info->op_chan; ++ ++ if (!vif) ++ return; ++ ++ rtwdev->hal.rcr |= BIT_CBSSID_BCN; ++ rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); ++ ++ rtw_core_scan_complete(rtwdev, vif, true); ++ ++ rtwvif = (struct rtw_vif *)vif->drv_priv; ++ if (chan) ++ rtw_store_op_chan(rtwdev, false); ++ rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); ++ ieee80211_wake_queues(rtwdev->hw); ++ ieee80211_scan_completed(rtwdev->hw, &info); ++ ++ rtwvif->scan_req = NULL; ++ rtwvif->scan_ies = NULL; ++ rtwdev->scan_info.scanning_vif = NULL; ++} ++ ++static int rtw_hw_scan_prehandle(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ++ struct rtw_chan_list *list) ++{ ++ struct cfg80211_scan_request *req = rtwvif->scan_req; ++ int size = req->n_channels * (RTW_CH_INFO_SIZE + RTW_EX_CH_INFO_SIZE); ++ u8 *buf; ++ int ret; ++ ++ buf = kmalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = rtw_hw_scan_update_probe_req(rtwdev, rtwvif); ++ if (ret) { ++ rtw_err(rtwdev, "Update probe request failed\n"); ++ goto out; ++ } ++ ++ list->buf_size = size; ++ list->size = 0; ++ list->ch_num = 0; ++ ret = rtw_add_chan_list(rtwdev, rtwvif, list, buf); ++out: ++ kfree(buf); ++ ++ return ret; ++} ++ ++int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool enable) ++{ ++ struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL; ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ struct rtw_ch_switch_option cs_option = {0}; ++ struct rtw_chan_list chan_list = {0}; ++ int ret = 0; ++ ++ if (!rtwvif) ++ return -EINVAL; ++ ++ cs_option.switch_en = enable; ++ cs_option.back_op_en = scan_info->op_chan != 0; ++ if (enable) { ++ ret = rtw_hw_scan_prehandle(rtwdev, rtwvif, &chan_list); ++ if (ret) ++ goto out; ++ } ++ rtw_fw_set_scan_offload(rtwdev, &cs_option, rtwvif, &chan_list); ++out: ++ if (rtwdev->ap_active) { ++ ret = rtw_download_beacon(rtwdev); ++ if (ret) ++ rtw_err(rtwdev, "HW scan download beacon failed\n"); ++ } ++ ++ return ret; ++} ++ ++void rtw_hw_scan_abort(struct rtw_dev *rtwdev) ++{ ++ struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD)) ++ return; ++ ++ rtw_hw_scan_offload(rtwdev, vif, false); ++ rtw_hw_scan_complete(rtwdev, vif, true); ++} ++ ++void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb) ++{ ++ struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; ++ struct rtw_c2h_cmd *c2h; ++ bool aborted; ++ u8 rc; ++ ++ if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ return; ++ ++ c2h = get_c2h_from_skb(skb); ++ rc = GET_SCAN_REPORT_RETURN_CODE(c2h->payload); ++ aborted = rc != RTW_SCAN_REPORT_SUCCESS; ++ rtw_hw_scan_complete(rtwdev, vif, aborted); ++ ++ if (aborted) ++ rtw_dbg(rtwdev, RTW_DBG_HW_SCAN, "HW scan aborted with code: %d\n", rc); ++} ++ ++void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup) ++{ ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 band; ++ ++ if (backup) { ++ scan_info->op_chan = hal->current_channel; ++ scan_info->op_bw = hal->current_band_width; ++ scan_info->op_pri_ch_idx = hal->current_primary_channel_index; ++ scan_info->op_pri_ch = hal->primary_channel; ++ } else { ++ band = scan_info->op_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; ++ rtw_update_channel(rtwdev, scan_info->op_chan, ++ scan_info->op_pri_ch, ++ band, scan_info->op_bw); ++ } ++} ++ ++void rtw_clear_op_chan(struct rtw_dev *rtwdev) ++{ ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ ++ scan_info->op_chan = 0; ++ scan_info->op_bw = 0; ++ scan_info->op_pri_ch_idx = 0; ++ scan_info->op_pri_ch = 0; ++} ++ ++static bool rtw_is_op_chan(struct rtw_dev *rtwdev, u8 channel) ++{ ++ struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info; ++ ++ return channel == scan_info->op_chan; ++} ++ ++void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_c2h_cmd *c2h; ++ enum rtw_scan_notify_id id; ++ u8 chan, band, status; ++ ++ if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ return; ++ ++ c2h = get_c2h_from_skb(skb); ++ chan = GET_CHAN_SWITCH_CENTRAL_CH(c2h->payload); ++ id = GET_CHAN_SWITCH_ID(c2h->payload); ++ status = GET_CHAN_SWITCH_STATUS(c2h->payload); ++ ++ if (id == RTW_SCAN_NOTIFY_ID_POSTSWITCH) { ++ band = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; ++ rtw_update_channel(rtwdev, chan, chan, band, ++ RTW_CHANNEL_WIDTH_20); ++ if (rtw_is_op_chan(rtwdev, chan)) { ++ rtw_store_op_chan(rtwdev, false); ++ ieee80211_wake_queues(rtwdev->hw); ++ rtw_core_enable_beacon(rtwdev, true); ++ } ++ } else if (id == RTW_SCAN_NOTIFY_ID_PRESWITCH) { ++ if (IS_CH_5G_BAND(chan)) { ++ rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G); ++ } else if (IS_CH_2G_BAND(chan)) { ++ u8 chan_type; ++ ++ if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ chan_type = COEX_SWITCH_TO_24G; ++ else ++ chan_type = COEX_SWITCH_TO_24G_NOFORSCAN; ++ rtw_coex_switchband_notify(rtwdev, chan_type); ++ } ++ /* The channel of C2H RTW_SCAN_NOTIFY_ID_PRESWITCH is next ++ * channel that hardware will switch. We need to stop queue ++ * if next channel is non-op channel. ++ */ ++ if (!rtw_is_op_chan(rtwdev, chan) && ++ rtw_is_op_chan(rtwdev, hal->current_channel)) { ++ rtw_core_enable_beacon(rtwdev, false); ++ ieee80211_stop_queues(rtwdev->hw); ++ } ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_HW_SCAN, ++ "Chan switch: %x, id: %x, status: %x\n", chan, id, status); ++} +diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h +index f4aed247e3bd..1500723d1aa0 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.h ++++ b/drivers/net/wireless/realtek/rtw88/fw.h +@@ -24,19 +24,46 @@ + #define DLFW_BLK_SIZE_LEGACY 4 + #define FW_START_ADDR_LEGACY 0x1000 + ++#define BCN_LOSS_CNT 10 ++#define BCN_FILTER_NOTIFY_SIGNAL_CHANGE 0 ++#define BCN_FILTER_CONNECTION_LOSS 1 ++#define BCN_FILTER_CONNECTED 2 ++#define BCN_FILTER_NOTIFY_BEACON_LOSS 3 ++ ++#define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10) ++ ++#define RTW_CHANNEL_TIME 45 ++#define RTW_OFF_CHAN_TIME 100 ++#define RTW_PASS_CHAN_TIME 105 ++#define RTW_DFS_CHAN_TIME 20 ++#define RTW_CH_INFO_SIZE 4 ++#define RTW_EX_CH_INFO_SIZE 3 ++#define RTW_EX_CH_INFO_HDR_SIZE 2 ++#define RTW_SCAN_WIDTH 0 ++#define RTW_PRI_CH_IDX 1 ++#define RTW_OLD_PROBE_PG_CNT 2 ++#define RTW_PROBE_PG_CNT 4 ++ + enum rtw_c2h_cmd_id { + C2H_CCX_TX_RPT = 0x03, + C2H_BT_INFO = 0x09, + C2H_BT_MP_INFO = 0x0b, ++ C2H_BT_HID_INFO = 0x45, + C2H_RA_RPT = 0x0c, + C2H_HW_FEATURE_REPORT = 0x19, + C2H_WLAN_INFO = 0x27, ++ C2H_WLAN_RFON = 0x32, ++ C2H_BCN_FILTER_NOTIFY = 0x36, ++ C2H_ADAPTIVITY = 0x37, ++ C2H_SCAN_RESULT = 0x38, + C2H_HW_FEATURE_DUMP = 0xfd, + C2H_HALMAC = 0xff, + }; + + enum rtw_c2h_cmd_id_ext { ++ C2H_SCAN_STATUS_RPT = 0x3, + C2H_CCX_RPT = 0x0f, ++ C2H_CHAN_SWITCH = 0x22, + }; + + struct rtw_c2h_cmd { +@@ -45,6 +72,31 @@ struct rtw_c2h_cmd { + u8 payload[]; + } __packed; + ++struct rtw_c2h_adaptivity { ++ u8 density; ++ u8 igi; ++ u8 l2h_th_init; ++ u8 l2h; ++ u8 h2l; ++ u8 option; ++} __packed; ++ ++struct rtw_h2c_register { ++ u32 w0; ++ u32 w1; ++} __packed; ++ ++#define RTW_H2C_W0_CMDID GENMASK(7, 0) ++ ++/* H2C_CMD_DEFAULT_PORT command */ ++#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8) ++#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16) ++ ++struct rtw_h2c_cmd { ++ __le32 msg; ++ __le32 msg_ext; ++} __packed; ++ + enum rtw_rsvd_packet_type { + RSVD_BEACON, + RSVD_DUMMY, +@@ -72,6 +124,32 @@ enum rtw_fw_rf_type { + FW_RF_MAX_TYPE = 0xF, + }; + ++enum rtw_fw_feature { ++ FW_FEATURE_SIG = BIT(0), ++ FW_FEATURE_LPS_C2H = BIT(1), ++ FW_FEATURE_LCLK = BIT(2), ++ FW_FEATURE_PG = BIT(3), ++ FW_FEATURE_TX_WAKE = BIT(4), ++ FW_FEATURE_BCN_FILTER = BIT(5), ++ FW_FEATURE_NOTIFY_SCAN = BIT(6), ++ FW_FEATURE_ADAPTIVITY = BIT(7), ++ FW_FEATURE_SCAN_OFFLOAD = BIT(8), ++ FW_FEATURE_MAX = BIT(31), ++}; ++ ++enum rtw_fw_feature_ext { ++ FW_FEATURE_EXT_OLD_PAGE_NUM = BIT(0), ++}; ++ ++enum rtw_beacon_filter_offload_mode { ++ BCN_FILTER_OFFLOAD_MODE_0 = 0, ++ BCN_FILTER_OFFLOAD_MODE_1, ++ BCN_FILTER_OFFLOAD_MODE_2, ++ BCN_FILTER_OFFLOAD_MODE_3, ++ ++ BCN_FILTER_OFFLOAD_MODE_DEFAULT = BCN_FILTER_OFFLOAD_MODE_0, ++}; ++ + struct rtw_coex_info_req { + u8 seq; + u8 op_code; +@@ -115,6 +193,7 @@ struct rtw_rsvd_page { + struct sk_buff *skb; + enum rtw_rsvd_packet_type type; + u8 page; ++ u16 tim_offset; + bool add_txdesc; + struct cfg80211_ssid *ssid; + u16 probe_req_size; +@@ -155,6 +234,51 @@ struct rtw_fw_wow_disconnect_para { + u8 retry_count; + }; + ++enum rtw_channel_type { ++ RTW_CHANNEL_PASSIVE, ++ RTW_CHANNEL_ACTIVE, ++ RTW_CHANNEL_RADAR, ++}; ++ ++enum rtw_scan_extra_id { ++ RTW_SCAN_EXTRA_ID_DFS, ++}; ++ ++enum rtw_scan_extra_info { ++ RTW_SCAN_EXTRA_ACTION_SCAN, ++}; ++ ++enum rtw_scan_report_code { ++ RTW_SCAN_REPORT_SUCCESS = 0x00, ++ RTW_SCAN_REPORT_ERR_PHYDM = 0x01, ++ RTW_SCAN_REPORT_ERR_ID = 0x02, ++ RTW_SCAN_REPORT_ERR_TX = 0x03, ++ RTW_SCAN_REPORT_CANCELED = 0x10, ++ RTW_SCAN_REPORT_CANCELED_EXT = 0x11, ++ RTW_SCAN_REPORT_FW_DISABLED = 0xF0, ++}; ++ ++enum rtw_scan_notify_id { ++ RTW_SCAN_NOTIFY_ID_PRESWITCH = 0x00, ++ RTW_SCAN_NOTIFY_ID_POSTSWITCH = 0x01, ++ RTW_SCAN_NOTIFY_ID_PROBE_PRETX = 0x02, ++ RTW_SCAN_NOTIFY_ID_PROBE_ISSUETX = 0x03, ++ RTW_SCAN_NOTIFY_ID_NULL0_PRETX = 0x04, ++ RTW_SCAN_NOTIFY_ID_NULL0_ISSUETX = 0x05, ++ RTW_SCAN_NOTIFY_ID_NULL0_POSTTX = 0x06, ++ RTW_SCAN_NOTIFY_ID_NULL1_PRETX = 0x07, ++ RTW_SCAN_NOTIFY_ID_NULL1_ISSUETX = 0x08, ++ RTW_SCAN_NOTIFY_ID_NULL1_POSTTX = 0x09, ++ RTW_SCAN_NOTIFY_ID_DWELLEXT = 0x0A, ++}; ++ ++enum rtw_scan_notify_status { ++ RTW_SCAN_NOTIFY_STATUS_SUCCESS = 0x00, ++ RTW_SCAN_NOTIFY_STATUS_FAILURE = 0x01, ++ RTW_SCAN_NOTIFY_STATUS_RESOURCE = 0x02, ++ RTW_SCAN_NOTIFY_STATUS_TIMEOUT = 0x03, ++}; ++ + struct rtw_ch_switch_option { + u8 periodic_option; + u32 tsf_high; +@@ -168,6 +292,8 @@ struct rtw_ch_switch_option { + u8 slow_period; + u8 slow_period_sel; + u8 nlo_en; ++ bool switch_en; ++ bool back_op_en; + }; + + struct rtw_fw_hdr { +@@ -178,7 +304,7 @@ struct rtw_fw_hdr { + u8 subversion; + u8 subindex; + __le32 rsvd; /* 0x08 */ +- __le32 rsvd2; /* 0x0C */ ++ __le32 feature; /* 0x0C */ + u8 month; /* 0x10 */ + u8 day; + u8 hour; +@@ -218,17 +344,31 @@ struct rtw_fw_hdr_legacy { + __le32 rsvd5; + } __packed; + ++#define RTW_FW_VER_CODE(ver, sub_ver, idx) \ ++ (((ver) << 16) | ((sub_ver) << 8) | (idx)) ++#define RTW_FW_SUIT_VER_CODE(s) \ ++ RTW_FW_VER_CODE((s).version, (s).sub_version, (s).sub_index) ++ + /* C2H */ + #define GET_CCX_REPORT_SEQNUM_V0(c2h_payload) (c2h_payload[6] & 0xfc) + #define GET_CCX_REPORT_STATUS_V0(c2h_payload) (c2h_payload[0] & 0xc0) + #define GET_CCX_REPORT_SEQNUM_V1(c2h_payload) (c2h_payload[8] & 0xfc) + #define GET_CCX_REPORT_STATUS_V1(c2h_payload) (c2h_payload[9] & 0xc0) + ++#define GET_SCAN_REPORT_RETURN_CODE(c2h_payload) (c2h_payload[2] & 0xff) ++ ++#define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload) (c2h_payload[2]) ++#define GET_CHAN_SWITCH_ID(c2h_payload) (c2h_payload[3]) ++#define GET_CHAN_SWITCH_STATUS(c2h_payload) (c2h_payload[4]) + #define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f) + #define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7) + #define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6]) + #define GET_RA_REPORT_MACID(c2h_payload) (c2h_payload[1]) + ++#define GET_BCN_FILTER_NOTIFY_TYPE(c2h_payload) (c2h_payload[1] & 0xf) ++#define GET_BCN_FILTER_NOTIFY_EVENT(c2h_payload) (c2h_payload[1] & 0x10) ++#define GET_BCN_FILTER_NOTIFY_RSSI(c2h_payload) (c2h_payload[2] - 100) ++ + /* PKT H2C */ + #define H2C_PKT_CMD_ID 0xFF + #define H2C_PKT_CATEGORY 0x01 +@@ -239,6 +379,7 @@ struct rtw_fw_hdr_legacy { + + #define H2C_PKT_CH_SWITCH 0x02 + #define H2C_PKT_UPDATE_PKT 0x0C ++#define H2C_PKT_SCAN_OFFLOAD 0x19 + + #define H2C_PKT_CH_SWITCH_LEN 0x20 + #define H2C_PKT_UPDATE_PKT_LEN 0x4 +@@ -289,6 +430,30 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16)) + #define CHSW_INFO_SET_ACTION_ID(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24)) ++#define CHSW_INFO_SET_EXTRA_INFO(pkt, value) \ ++ le32p_replace_bits((__le32 *)(pkt) + 0x00, value, BIT(31)) ++ ++#define CH_INFO_SET_CH(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x00, value, GENMASK(7, 0)) ++#define CH_INFO_SET_PRI_CH_IDX(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(3, 0)) ++#define CH_INFO_SET_BW(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(7, 4)) ++#define CH_INFO_SET_TIMEOUT(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x02, value, GENMASK(7, 0)) ++#define CH_INFO_SET_ACTION_ID(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x03, value, GENMASK(6, 0)) ++#define CH_INFO_SET_EXTRA_INFO(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x03, value, BIT(7)) ++ ++#define EXTRA_CH_INFO_SET_ID(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x04, value, GENMASK(6, 0)) ++#define EXTRA_CH_INFO_SET_INFO(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x04, value, BIT(7)) ++#define EXTRA_CH_INFO_SET_SIZE(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x05, value, GENMASK(7, 0)) ++#define EXTRA_CH_INFO_SET_DFS_EXT_TIME(pkt, value) \ ++ u8p_replace_bits((u8 *)(pkt) + 0x06, value, GENMASK(7, 0)) + + #define UPDATE_PKT_SET_SIZE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0)) +@@ -305,12 +470,18 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2)) + #define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3)) ++#define CH_SWITCH_SET_SCAN_MODE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(5)) ++#define CH_SWITCH_SET_BACK_OP_EN(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(6)) + #define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8)) + #define CH_SWITCH_SET_CH_NUM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) + #define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24)) ++#define CH_SWITCH_SET_DEST_BW(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28)) + #define CH_SWITCH_SET_DEST_CH(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0)) + #define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value) \ +@@ -330,13 +501,54 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0)) + ++#define SCAN_OFFLOAD_SET_START(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0)) ++#define SCAN_OFFLOAD_SET_BACK_OP_EN(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1)) ++#define SCAN_OFFLOAD_SET_RANDOM_SEQ_EN(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2)) ++#define SCAN_OFFLOAD_SET_NO_CCK_EN(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(3)) ++#define SCAN_OFFLOAD_SET_VERBOSE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(4)) ++#define SCAN_OFFLOAD_SET_CH_NUM(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8)) ++#define SCAN_OFFLOAD_SET_CH_INFO_SIZE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 16)) ++#define SCAN_OFFLOAD_SET_CH_INFO_LOC(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0)) ++#define SCAN_OFFLOAD_SET_OP_CH(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 8)) ++#define SCAN_OFFLOAD_SET_OP_PRI_CH_IDX(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(19, 16)) ++#define SCAN_OFFLOAD_SET_OP_BW(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 20)) ++#define SCAN_OFFLOAD_SET_OP_PORT_ID(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(26, 24)) ++#define SCAN_OFFLOAD_SET_OP_DWELL_TIME(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(15, 0)) ++#define SCAN_OFFLOAD_SET_OP_GAP_TIME(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 16)) ++#define SCAN_OFFLOAD_SET_MODE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(3, 0)) ++#define SCAN_OFFLOAD_SET_SSID_NUM(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(7, 4)) ++#define SCAN_OFFLOAD_SET_PKT_LOC(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(15, 8)) ++ + /* Command H2C */ + #define H2C_CMD_RSVD_PAGE 0x0 + #define H2C_CMD_MEDIA_STATUS_RPT 0x01 + #define H2C_CMD_SET_PWR_MODE 0x20 + #define H2C_CMD_LPS_PG_INFO 0x2b ++#define H2C_CMD_DEFAULT_PORT 0x2c + #define H2C_CMD_RA_INFO 0x40 + #define H2C_CMD_RSSI_MONITOR 0x42 ++#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56 ++#define H2C_CMD_BCN_FILTER_OFFLOAD_P1 0x57 ++#define H2C_CMD_WL_PHY_INFO 0x58 ++#define H2C_CMD_SCAN 0x59 ++#define H2C_CMD_ADAPTIVITY 0x5A + + #define H2C_CMD_COEX_TDMA_TYPE 0x60 + #define H2C_CMD_QUERY_BT_INFO 0x61 +@@ -345,6 +557,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define H2C_CMD_WL_CH_INFO 0x66 + #define H2C_CMD_QUERY_BT_MP_INFO 0x67 + #define H2C_CMD_BT_WIFI_CONTROL 0x69 ++#define H2C_CMD_WIFI_CALIBRATION 0x6d ++#define H2C_CMD_QUERY_BT_HID_INFO 0x73 + + #define H2C_CMD_KEEP_ALIVE 0x03 + #define H2C_CMD_DISCONNECT_DECISION 0x04 +@@ -353,6 +567,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define H2C_CMD_AOAC_GLOBAL_INFO 0x82 + #define H2C_CMD_NLO_INFO 0x8C + ++#define H2C_CMD_RECOVER_BT_DEV 0xD1 ++ + #define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) + +@@ -361,6 +577,45 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + ++#define SET_WL_PHY_INFO_TX_TP(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(17, 8)) ++#define SET_WL_PHY_INFO_RX_TP(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(27, 18)) ++#define SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) ++#define SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) ++#define SET_WL_PHY_INFO_RX_EVM(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) ++#define SET_BCN_FILTER_OFFLOAD_P1_MACID(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) ++#define SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(16)) ++#define SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(20, 17)) ++#define SET_BCN_FILTER_OFFLOAD_P1_OFFLOAD_MODE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 21)) ++#define SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) ++#define SET_BCN_FILTER_OFFLOAD_P1_BCN_LOSS_CNT(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(3, 0)) ++#define SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(13, 4)) ++ ++#define SET_SCAN_START(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) ++ ++#define SET_ADAPTIVITY_MODE(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(11, 8)) ++#define SET_ADAPTIVITY_OPTION(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12)) ++#define SET_ADAPTIVITY_IGI(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) ++#define SET_ADAPTIVITY_L2H(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) ++#define SET_ADAPTIVITY_DENSITY(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) ++ + #define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8)) + #define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \ +@@ -458,6 +713,11 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) + ++#define SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) ++#define SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) ++ + #define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) + #define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value) \ +@@ -508,6 +768,9 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + ++#define SET_RECOVER_BT_DEV_EN(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) ++ + #define GET_FW_DUMP_LEN(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(15, 0)) + #define GET_FW_DUMP_SEQ(_header) \ +@@ -522,6 +785,9 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + le32_get_bits(*((__le32 *)(_header) + 0x01), GENMASK(31, 16)) + #define GET_FW_DUMP_TLV_VAL(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x02), GENMASK(31, 0)) ++ ++#define RFK_SET_INFORM_START(h2c_pkt, value) \ ++ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) + static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) + { + u32 pkt_offset; +@@ -530,13 +796,27 @@ static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) + return (struct rtw_c2h_cmd *)(skb->data + pkt_offset); + } + ++static inline bool rtw_fw_feature_check(struct rtw_fw_state *fw, ++ enum rtw_fw_feature feature) ++{ ++ return !!(fw->feature & feature); ++} ++ ++static inline bool rtw_fw_feature_ext_check(struct rtw_fw_state *fw, ++ enum rtw_fw_feature_ext feature) ++{ ++ return !!(fw->feature_ext & feature); ++} ++ + void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, + struct sk_buff *skb); + void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); + void rtw_fw_send_general_info(struct rtw_dev *rtwdev); + void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev); ++void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); + + void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para); ++void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start); + void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev); + void rtw_fw_set_pg_info(struct rtw_dev *rtwdev); + void rtw_fw_query_bt_info(struct rtw_dev *rtwdev); +@@ -547,10 +827,20 @@ void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl); + void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable); + void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev, + u8 para1, u8 para2, u8 para3, u8 para4, u8 para5); ++void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data); ++ + void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data); + void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, ++ bool reset_ra_mask); ++#else + void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); ++#endif + void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); ++void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev); ++void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect, ++ struct ieee80211_vif *vif); + int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + u8 *buf, u32 size); + void rtw_remove_rsvd_page(struct rtw_dev *rtwdev, +@@ -562,6 +852,7 @@ void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev, + void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif); + int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev); ++void rtw_fw_update_beacon_work(struct work_struct *work); + void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev); + int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, + u32 offset, u32 size, u32 *buf); +@@ -574,6 +865,7 @@ void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev, + u8 group_key_enc); + + void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable); ++void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev); + void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid); + void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable); +@@ -581,5 +873,17 @@ void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c); + void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev); + int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, + u32 *buffer); +- ++void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start); ++void rtw_fw_adaptivity(struct rtw_dev *rtwdev); ++void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup); ++void rtw_clear_op_chan(struct rtw_dev *rtwdev); ++void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ struct ieee80211_scan_request *req); ++void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool aborted); ++int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool enable); ++void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb); ++void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb); ++void rtw_hw_scan_abort(struct rtw_dev *rtwdev); + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h +index 2cba327e6218..830d7532f2a3 100644 +--- a/drivers/net/wireless/realtek/rtw88/hci.h ++++ b/drivers/net/wireless/realtek/rtw88/hci.h +@@ -11,6 +11,7 @@ struct rtw_hci_ops { + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb); + void (*tx_kick_off)(struct rtw_dev *rtwdev); ++ void (*flush_queues)(struct rtw_dev *rtwdev, u32 queues, bool drop); + int (*setup)(struct rtw_dev *rtwdev); + int (*start)(struct rtw_dev *rtwdev); + void (*stop)(struct rtw_dev *rtwdev); +@@ -165,12 +166,11 @@ static inline u32 + rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask) + { +- unsigned long flags; + u32 val; + +- spin_lock_irqsave(&rtwdev->rf_lock, flags); ++ lockdep_assert_held(&rtwdev->mutex); ++ + val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask); +- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); + + return val; + } +@@ -179,11 +179,9 @@ static inline void + rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) + { +- unsigned long flags; ++ lockdep_assert_held(&rtwdev->mutex); + +- spin_lock_irqsave(&rtwdev->rf_lock, flags); + rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data); +- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); + } + + static inline u32 +@@ -258,4 +256,19 @@ static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev) + return rtwdev->hci.type; + } + ++static inline void rtw_hci_flush_queues(struct rtw_dev *rtwdev, u32 queues, ++ bool drop) ++{ ++ if (rtwdev->hci.ops->flush_queues) ++ rtwdev->hci.ops->flush_queues(rtwdev, queues, drop); ++} ++ ++static inline void rtw_hci_flush_all_queues(struct rtw_dev *rtwdev, bool drop) ++{ ++ if (rtwdev->hci.ops->flush_queues) ++ rtwdev->hci.ops->flush_queues(rtwdev, ++ BIT(rtwdev->hw->queues) - 1, ++ drop); ++} ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index 59028b121b00..0c1c1ff31085 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -7,6 +7,7 @@ + #include "reg.h" + #include "fw.h" + #include "debug.h" ++#include "sdio.h" + + void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx) +@@ -60,6 +61,7 @@ EXPORT_SYMBOL(rtw_set_channel_mac); + + static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) + { ++ unsigned int retry; + u32 value32; + u8 value8; + +@@ -75,7 +77,29 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: +- rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN); ++ rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS); ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rtw_write8_clr(rtwdev, REG_SDIO_HSUS_CTRL, BIT_HCI_SUS_REQ); ++ ++ for (retry = 0; retry < RTW_PWR_POLLING_CNT; retry++) { ++ if (rtw_read8(rtwdev, REG_SDIO_HSUS_CTRL) & BIT_HCI_RESUME_RDY) ++ break; ++ ++ usleep_range(10, 50); ++ } ++ ++ if (retry == RTW_PWR_POLLING_CNT) { ++ rtw_err(rtwdev, "failed to poll REG_SDIO_HSUS_CTRL[1]"); ++ return -ETIMEDOUT; ++ } ++ ++ if (rtw_sdio_is_sdio30_supported(rtwdev)) ++ rtw_write8_set(rtwdev, REG_HCI_OPT_CTRL + 2, ++ BIT_SDIO_PAD_E5 >> 16); ++ else ++ rtw_write8_clr(rtwdev, REG_HCI_OPT_CTRL + 2, ++ BIT_SDIO_PAD_E5 >> 16); + break; + case RTW_HCI_TYPE_USB: + break; +@@ -217,10 +241,13 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + cut_mask = cut_version_to_mask(cut); + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: +- intf_mask = BIT(2); ++ intf_mask = RTW_PWR_INTF_PCI_MSK; + break; + case RTW_HCI_TYPE_USB: +- intf_mask = BIT(1); ++ intf_mask = RTW_PWR_INTF_USB_MSK; ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ intf_mask = RTW_PWR_INTF_SDIO_MSK; + break; + default: + return -EINVAL; +@@ -233,7 +260,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + + ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd); + if (ret) +- return -EBUSY; ++ return ret; + + idx++; + } while (1); +@@ -243,10 +270,12 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + + static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_pwr_seq_cmd **pwr_seq; ++ u32 imr = 0; + u8 rpwm; + bool cur_pwr; ++ int ret; + + if (rtw_chip_wcpu_11ac(rtwdev)) { + rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); +@@ -269,11 +298,31 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + if (pwr_on == cur_pwr) + return -EALREADY; + ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { ++ imr = rtw_read32(rtwdev, REG_SDIO_HIMR); ++ rtw_write32(rtwdev, REG_SDIO_HIMR, 0); ++ } ++ ++ if (!pwr_on) ++ clear_bit(RTW_FLAG_POWERON, rtwdev->flags); ++ + pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq; +- if (rtw_pwr_seq_parser(rtwdev, pwr_seq)) +- return -EINVAL; ++ ret = rtw_pwr_seq_parser(rtwdev, pwr_seq); + +- return 0; ++ if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { ++ if (chip->id == RTW_CHIP_TYPE_8822C || ++ chip->id == RTW_CHIP_TYPE_8822B || ++ chip->id == RTW_CHIP_TYPE_8821C) ++ rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0)); ++ } ++ ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) ++ rtw_write32(rtwdev, REG_SDIO_HIMR, imr); ++ ++ if (!ret && pwr_on) ++ set_bit(RTW_FLAG_POWERON, rtwdev->flags); ++ ++ return ret; + } + + static int __rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) +@@ -335,6 +384,11 @@ int rtw_mac_power_on(struct rtw_dev *rtwdev) + ret = rtw_mac_power_switch(rtwdev, true); + if (ret == -EALREADY) { + rtw_mac_power_switch(rtwdev, false); ++ ++ ret = rtw_mac_pre_system_cfg(rtwdev); ++ if (ret) ++ goto err; ++ + ret = rtw_mac_power_switch(rtwdev, true); + if (ret) + goto err; +@@ -439,6 +493,9 @@ static void download_firmware_reg_backup(struct rtw_dev *rtwdev, + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200); + rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val); + ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) ++ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG); ++ + /* Disable beacon related functions */ + tmp = rtw_read8(rtwdev, REG_BCN_CTRL); + bckp[bckp_idx].len = 1; +@@ -530,6 +587,25 @@ static int iddma_download_firmware(struct rtw_dev *rtwdev, u32 src, u32 dst, + return 0; + } + ++int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size) ++{ ++ u32 ch0_ctrl = BIT_DDMACH0_OWN | BIT_DDMACH0_DDMA_MODE; ++ ++ if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0)) { ++ rtw_dbg(rtwdev, RTW_DBG_FW, "busy to start ddma\n"); ++ return -EBUSY; ++ } ++ ++ ch0_ctrl |= size & BIT_MASK_DDMACH0_DLEN; ++ ++ if (iddma_enable(rtwdev, ocp_src, OCPBASE_RXBUF_FW_88XX, ch0_ctrl)) { ++ rtw_dbg(rtwdev, RTW_DBG_FW, "busy to complete ddma\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ + static bool + check_fw_checksum(struct rtw_dev *rtwdev, u32 addr) + { +@@ -568,7 +644,7 @@ static int + download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data, + u32 src, u32 dst, u32 size) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u32 desc_size = chip->tx_pkt_desc_sz; + u8 first_part; + u32 mem_offset; +@@ -725,8 +801,10 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, + + wlan_cpu_enable(rtwdev, true); + +- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) +- return -EBUSY; ++ if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { ++ ret = -EBUSY; ++ goto dlfw_fail; ++ } + + ret = download_firmware_validate(rtwdev); + if (ret) +@@ -887,7 +965,8 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev, + return ret; + } + +-int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) ++static ++int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) + { + if (rtw_chip_wcpu_11n(rtwdev)) + return __rtw_download_firmware_legacy(rtwdev, fw); +@@ -895,6 +974,21 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) + return __rtw_download_firmware(rtwdev, fw); + } + ++int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) ++{ ++ int ret; ++ ++ ret = _rtw_download_firmware(rtwdev, fw); ++ if (ret) ++ return ret; ++ ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && ++ rtwdev->chip->id == RTW_CHIP_TYPE_8821C) ++ rtw_fw_set_recover_bt_device(rtwdev); ++ ++ return 0; ++} ++ + static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) + { + const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; +@@ -915,7 +1009,7 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) + static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, + u32 prio_queue, bool drop) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_prioq_addr *addr; + bool wsize; + u16 avail_page, rsvd_page; +@@ -977,7 +1071,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) + + static int txdma_queue_mapping(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_rqpn *rqpn = NULL; + u16 txdma_pq_map = 0; + +@@ -995,6 +1089,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) + else + return -EINVAL; + break; ++ case RTW_HCI_TYPE_SDIO: ++ rqpn = &chip->rqpn_table[0]; ++ break; + default: + return -EINVAL; + } +@@ -1013,18 +1110,25 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) + if (rtw_chip_wcpu_11ac(rtwdev)) + rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); + ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { ++ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG); ++ rtw_write32(rtwdev, REG_SDIO_TX_CTRL, 0); ++ } else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { ++ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN); ++ } ++ + return 0; + } + + static int set_trx_fifo_info(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fifo_conf *fifo = &rtwdev->fifo; +- struct rtw_chip_info *chip = rtwdev->chip; + u16 cur_pg_addr; + u8 csi_buf_pg_num = chip->csi_buf_pg_num; + + /* config rsvd page num */ +- fifo->rsvd_drv_pg_num = 8; ++ fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num; + fifo->txff_pg_num = chip->txff_size >> 7; + if (rtw_chip_wcpu_11n(rtwdev)) + fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num; +@@ -1073,8 +1177,8 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev, + const struct rtw_page_table *pg_tbl, + u16 pubq_num) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fifo_conf *fifo = &rtwdev->fifo; +- struct rtw_chip_info *chip = rtwdev->chip; + + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num); + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num); +@@ -1104,8 +1208,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev, + const struct rtw_page_table *pg_tbl, + u16 pubq_num) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fifo_conf *fifo = &rtwdev->fifo; +- struct rtw_chip_info *chip = rtwdev->chip; + u32 val32; + + val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num); +@@ -1130,8 +1234,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev, + + static int priority_queue_cfg(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fifo_conf *fifo = &rtwdev->fifo; +- struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_page_table *pg_tbl = NULL; + u16 pubq_num; + int ret; +@@ -1154,6 +1258,9 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) + else + return -EINVAL; + break; ++ case RTW_HCI_TYPE_SDIO: ++ pg_tbl = &chip->page_table[0]; ++ break; + default: + return -EINVAL; + } +@@ -1258,7 +1365,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) + + int rtw_mac_init(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + int ret; + + ret = rtw_init_trx_cfg(rtwdev); +diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h +index ce64cdf7a565..58c3dccc14bb 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.h ++++ b/drivers/net/wireless/realtek/rtw88/mac.h +@@ -7,7 +7,6 @@ + + #define RTW_HW_PORT_NUM 5 + #define cut_version_to_mask(cut) (0x1 << ((cut) + 1)) +-#define SDIO_LOCAL_OFFSET 0x10250000 + #define DDMA_POLLING_COUNT 1000 + #define C2H_PKT_BUF 256 + #define REPORT_BUF 128 +@@ -15,7 +14,10 @@ + #define ILLEGAL_KEY_GROUP 0xFAAAAA00 + + /* HW memory address */ ++#define OCPBASE_RXBUF_FW_88XX 0x18680000 + #define OCPBASE_TXBUF_88XX 0x18780000 ++#define OCPBASE_ROM_88XX 0x00000000 ++#define OCPBASE_IMEM_88XX 0x00030000 + #define OCPBASE_DMEM_88XX 0x00200000 + #define OCPBASE_EMEM_88XX 0x00100000 + +@@ -33,6 +35,7 @@ void rtw_mac_power_off(struct rtw_dev *rtwdev); + int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw); + int rtw_mac_init(struct rtw_dev *rtwdev); + void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop); ++int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size); + + static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop) + { +diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c +index c92fba2fa480..78bdbe2cf07b 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw88/mac80211.c +@@ -13,6 +13,9 @@ + #include "bf.h" + #include "debug.h" + #include "wow.h" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++#include "sar.h" ++#endif + + static void rtw_ops_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, +@@ -42,7 +45,11 @@ static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw, + list_add_tail(&rtwtxq->list, &rtwdev->txqs); + spin_unlock_bh(&rtwdev->txq_lock); + +- tasklet_schedule(&rtwdev->tx_tasklet); ++ /* ensure to dequeue EAPOL (4/4) at the right time */ ++ if (txq->ac == IEEE80211_AC_VO) ++ __rtw_tx_work(rtwdev); ++ else ++ queue_work(rtwdev->tx_wq, &rtwdev->tx_work); + } + + static int rtw_ops_start(struct ieee80211_hw *hw) +@@ -71,6 +78,9 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) + struct rtw_dev *rtwdev = hw->priv; + int ret = 0; + ++ /* let previous ips work finish to ensure we don't leave ips twice */ ++ cancel_work_sync(&rtwdev->ips_work); ++ + mutex_lock(&rtwdev->mutex); + + rtw_leave_lps_deep(rtwdev); +@@ -84,20 +94,12 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) + } + } + +- if (changed & IEEE80211_CONF_CHANGE_PS) { +- if (hw->conf.flags & IEEE80211_CONF_PS) { +- rtwdev->ps_enabled = true; +- } else { +- rtwdev->ps_enabled = false; +- rtw_leave_lps(rtwdev); +- } +- } +- + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + rtw_set_channel(rtwdev); + + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && +- (hw->conf.flags & IEEE80211_CONF_IDLE)) ++ (hw->conf.flags & IEEE80211_CONF_IDLE) && ++ !test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) + rtw_enter_ips(rtwdev); + + out: +@@ -150,21 +152,32 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + enum rtw_net_type net_type; + u32 config = 0; +- u8 port = 0; ++ u8 port; + u8 bcn_ctrl = 0; + +- rtwvif->port = port; ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER)) ++ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | ++ IEEE80211_VIF_SUPPORTS_CQM_RSSI; + rtwvif->stats.tx_unicast = 0; + rtwvif->stats.rx_unicast = 0; + rtwvif->stats.tx_cnt = 0; + rtwvif->stats.rx_cnt = 0; ++ rtwvif->scan_req = NULL; + memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee)); +- rtwvif->conf = &rtw_vif_port[port]; + rtw_txq_init(rtwdev, vif->txq); + INIT_LIST_HEAD(&rtwvif->rsvd_page_list); + + mutex_lock(&rtwdev->mutex); + ++ port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM); ++ if (port >= RTW_PORT_NUM) { ++ mutex_unlock(&rtwdev->mutex); ++ return -EINVAL; ++ } ++ set_bit(port, rtwdev->hw_port); ++ ++ rtwvif->port = port; ++ rtwvif->conf = &rtw_vif_port[port]; + rtw_leave_lps_deep(rtwdev); + + switch (vif->type) { +@@ -186,6 +199,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, + break; + default: + WARN_ON(1); ++ clear_bit(rtwvif->port, rtwdev->hw_port); + mutex_unlock(&rtwdev->mutex); + return -EINVAL; + } +@@ -197,10 +211,12 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, + rtwvif->bcn_ctrl = bcn_ctrl; + config |= PORT_SET_BCN_CTRL; + rtw_vif_port_config(rtwdev, rtwvif, config); ++ rtw_core_port_switch(rtwdev, vif); ++ rtw_recalc_lps(rtwdev, vif); + + mutex_unlock(&rtwdev->mutex); + +- rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port); ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM on port %d\n", vif->addr, rtwvif->port); + return 0; + } + +@@ -211,7 +227,7 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw, + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = 0; + +- rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port); ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM on port %d\n", vif->addr, rtwvif->port); + + mutex_lock(&rtwdev->mutex); + +@@ -227,6 +243,8 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw, + rtwvif->bcn_ctrl = 0; + config |= PORT_SET_BCN_CTRL; + rtw_vif_port_config(rtwdev, rtwvif, config); ++ clear_bit(rtwvif->port, rtwdev->hw_port); ++ rtw_recalc_lps(rtwdev, NULL); + + mutex_unlock(&rtwdev->mutex); + } +@@ -237,8 +255,8 @@ static int rtw_ops_change_interface(struct ieee80211_hw *hw, + { + struct rtw_dev *rtwdev = hw->priv; + +- rtw_info(rtwdev, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n", +- vif->addr, vif->type, type, vif->p2p, p2p); ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n", ++ vif->addr, vif->type, type, vif->p2p, p2p); + + rtw_ops_remove_interface(hw, vif); + +@@ -264,9 +282,9 @@ static void rtw_ops_configure_filter(struct ieee80211_hw *hw, + + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) +- rtwdev->hal.rcr |= BIT_AM | BIT_AB; ++ rtwdev->hal.rcr |= BIT_AM; + else +- rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB); ++ rtwdev->hal.rcr &= ~(BIT_AM); + } + if (changed_flags & FIF_FCSFAIL) { + if (*new_flags & FIF_FCSFAIL) +@@ -347,10 +365,16 @@ static void rtw_conf_tx(struct rtw_dev *rtwdev, + static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ u64 changed) ++#else + u32 changed) ++#endif + { + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; ++ struct rtw_coex *coex = &rtwdev->coex; ++ struct rtw_coex_stat *coex_stat = &coex->stat; + u32 config = 0; + + mutex_lock(&rtwdev->mutex); +@@ -359,17 +383,32 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + + if (changed & BSS_CHANGED_ASSOC) { + rtw_vif_assoc_changed(rtwvif, conf); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ if (vif->cfg.assoc) { ++#else + if (conf->assoc) { ++#endif + rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH); + + rtw_fw_download_rsvd_page(rtwdev); + rtw_send_rsvd_page_h2c(rtwdev); ++ rtw_fw_default_port(rtwdev, rtwvif); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc); ++#else + rtw_coex_media_status_notify(rtwdev, conf->assoc); ++#endif + if (rtw_bf_support) + rtw_bf_assoc(rtwdev, vif, conf); + } else { + rtw_leave_lps(rtwdev); + rtw_bf_disassoc(rtwdev, vif, conf); ++ /* Abort ongoing scan if cancel_scan isn't issued ++ * when disconnected by peer ++ */ ++ if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ rtw_hw_scan_abort(rtwdev); ++ + } + + config |= PORT_SET_NET_TYPE; +@@ -379,10 +418,22 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + if (changed & BSS_CHANGED_BSSID) { + ether_addr_copy(rtwvif->bssid, conf->bssid); + config |= PORT_SET_BSSID; ++ if (!rtw_core_check_sta_active(rtwdev)) ++ rtw_clear_op_chan(rtwdev); ++ else ++ rtw_store_op_chan(rtwdev, true); + } + +- if (changed & BSS_CHANGED_BEACON) ++ if (changed & BSS_CHANGED_BEACON_INT) { ++ if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) ++ coex_stat->wl_beacon_interval = conf->beacon_int; ++ } ++ ++ if (changed & BSS_CHANGED_BEACON) { ++ rtw_set_dtim_period(rtwdev, conf->dtim_period); + rtw_fw_download_rsvd_page(rtwdev); ++ rtw_send_rsvd_page_h2c(rtwdev); ++ } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (conf->enable_beacon) +@@ -392,6 +443,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + rtw_write32_clr(rtwdev, REG_FWHW_TXQ_CTRL, + BIT_EN_BCNQ_DL); + } ++ if (changed & BSS_CHANGED_CQM) ++ rtw_fw_beacon_filter_config(rtwdev, true, vif); + + if (changed & BSS_CHANGED_MU_GROUPS) + rtw_chip_set_gid_table(rtwdev, vif, conf); +@@ -399,13 +452,61 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + if (changed & BSS_CHANGED_ERP_SLOT) + rtw_conf_tx(rtwdev, rtwvif); + ++ if (changed & BSS_CHANGED_PS) ++ rtw_recalc_lps(rtwdev, NULL); ++ + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++static int rtw_ops_start_ap(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *link_conf) ++#else ++static int rtw_ops_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++#endif ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); ++ rtwdev->ap_active = true; ++ rtw_store_op_chan(rtwdev, true); ++ chip->ops->phy_calibration(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++ ++ return 0; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++static void rtw_ops_stop_ap(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *link_conf) ++#else ++static void rtw_ops_stop_ap(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++#endif ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); ++ rtwdev->ap_active = false; ++ if (!rtw_core_check_sta_active(rtwdev)) ++ rtw_clear_op_chan(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++} ++ + static int rtw_ops_conf_tx(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, u16 ac, ++ struct ieee80211_vif *vif, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ unsigned int link_id, u16 ac, ++#else ++ u16 ac, ++#endif + const struct ieee80211_tx_queue_params *params) + { + struct rtw_dev *rtwdev = hw->priv; +@@ -444,12 +545,23 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw, + struct rtw_dev *rtwdev = hw->priv; + + mutex_lock(&rtwdev->mutex); ++ rtw_fw_beacon_filter_config(rtwdev, false, vif); + rtw_sta_remove(rtwdev, sta, true); + mutex_unlock(&rtwdev->mutex); + + return 0; + } + ++static int rtw_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, ++ bool set) ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ ++ ieee80211_queue_work(hw, &rtwdev->update_beacon_work); ++ ++ return 0; ++} ++ + static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +@@ -513,13 +625,14 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + hw_key_type, hw_key_idx); + break; + case DISABLE_KEY: ++ rtw_hci_flush_all_queues(rtwdev, false); + rtw_mac_flush_all_queues(rtwdev, false); + rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); + break; + } + + /* download new cam settings for PG to backup */ +- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG) ++ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) + rtw_fw_download_rsvd_page(rtwdev); + + out: +@@ -528,18 +641,35 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + return ret; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) + static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) ++#else ++static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ enum ieee80211_ampdu_mlme_action action, ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, ++ u8 buf_size, bool amsdu) ++#endif + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) + struct ieee80211_sta *sta = params->sta; + u16 tid = params->tid; + struct ieee80211_txq *txq = sta->txq[tid]; + struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv; + + switch (params->action) { ++#else ++ switch (action) { ++#endif + case IEEE80211_AMPDU_TX_START: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) + return IEEE80211_AMPDU_TX_START_IMMEDIATE; ++#else ++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ break; ++#endif + case IEEE80211_AMPDU_TX_STOP_CONT: + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: +@@ -560,6 +690,7 @@ static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, + return 0; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) + static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw, + struct sk_buff *head, + struct sk_buff *skb) +@@ -573,6 +704,7 @@ static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw, + + return true; + } ++#endif + + static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -580,21 +712,9 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, + { + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; +- u32 config = 0; + + mutex_lock(&rtwdev->mutex); +- +- rtw_leave_lps(rtwdev); +- +- ether_addr_copy(rtwvif->mac_addr, mac_addr); +- config |= PORT_SET_MAC_ADDR; +- rtw_vif_port_config(rtwdev, rtwvif, config); +- +- rtw_coex_scan_notify(rtwdev, COEX_SCAN_START); +- +- set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags); +- set_bit(RTW_FLAG_SCANNING, rtwdev->flags); +- ++ rtw_core_scan_start(rtwdev, rtwvif, mac_addr, false); + mutex_unlock(&rtwdev->mutex); + } + +@@ -602,26 +722,24 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; +- u32 config = 0; + + mutex_lock(&rtwdev->mutex); +- +- clear_bit(RTW_FLAG_SCANNING, rtwdev->flags); +- clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags); +- +- ether_addr_copy(rtwvif->mac_addr, vif->addr); +- config |= PORT_SET_MAC_ADDR; +- rtw_vif_port_config(rtwdev, rtwvif, config); +- +- rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH); +- ++ rtw_core_scan_complete(rtwdev, vif, false); + mutex_unlock(&rtwdev->mutex); + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) + static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,14,0)) ++ struct ieee80211_prep_tx_info *info) ++ #else + u16 duration) ++ #endif ++#else ++static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++#endif + { + struct rtw_dev *rtwdev = hw->priv; + +@@ -663,6 +781,7 @@ static void rtw_ops_flush(struct ieee80211_hw *hw, + mutex_lock(&rtwdev->mutex); + rtw_leave_lps_deep(rtwdev); + ++ rtw_hci_flush_queues(rtwdev, queues, drop); + rtw_mac_flush_queues(rtwdev, queues, drop); + mutex_unlock(&rtwdev->mutex); + } +@@ -691,7 +810,7 @@ static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) + } + + si->use_cfg_mask = true; +- rtw_update_sta_info(br_data->rtwdev, si); ++ rtw_update_sta_info(br_data->rtwdev, si, true); + } + + static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev, +@@ -703,7 +822,7 @@ static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev, + br_data.rtwdev = rtwdev; + br_data.vif = vif; + br_data.mask = mask; +- rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data); ++ rtw_iterate_stas(rtwdev, rtw_ra_mask_info_update_iter, &br_data); + } + + static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -712,7 +831,9 @@ static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw, + { + struct rtw_dev *rtwdev = hw->priv; + ++ mutex_lock(&rtwdev->mutex); + rtw_ra_mask_info_update(rtwdev, vif, mask); ++ mutex_unlock(&rtwdev->mutex); + + return 0; + } +@@ -722,7 +843,7 @@ static int rtw_ops_set_antenna(struct ieee80211_hw *hw, + u32 rx_antenna) + { + struct rtw_dev *rtwdev = hw->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + int ret; + + if (!chip->ops->set_antenna) +@@ -797,6 +918,71 @@ static void rtw_reconfig_complete(struct ieee80211_hw *hw, + mutex_unlock(&rtwdev->mutex); + } + ++static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_scan_request *req) ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ int ret; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD)) ++ return 1; ++ ++ if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ return -EBUSY; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_hw_scan_start(rtwdev, vif, req); ++ ret = rtw_hw_scan_offload(rtwdev, vif, true); ++ if (ret) { ++ rtw_hw_scan_abort(rtwdev); ++ rtw_err(rtwdev, "HW scan failed with status: %d\n", ret); ++ } ++ mutex_unlock(&rtwdev->mutex); ++ ++ return ret; ++} ++ ++static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD)) ++ return; ++ ++ if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ return; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_hw_scan_abort(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw, ++ const struct cfg80211_sar_specs *sar) ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_set_sar_specs(rtwdev, sar); ++ mutex_unlock(&rtwdev->mutex); ++ ++ return 0; ++} ++#endif ++ ++static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, u32 changed) ++{ ++ struct rtw_dev *rtwdev = hw->priv; ++ struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; ++ ++ if (changed & IEEE80211_RC_BW_CHANGED) ++ ieee80211_queue_work(rtwdev->hw, &si->rc_work); ++} ++ + const struct ieee80211_ops rtw_ops = { + .tx = rtw_ops_tx, + .wake_tx_queue = rtw_ops_wake_tx_queue, +@@ -808,12 +994,17 @@ const struct ieee80211_ops rtw_ops = { + .change_interface = rtw_ops_change_interface, + .configure_filter = rtw_ops_configure_filter, + .bss_info_changed = rtw_ops_bss_info_changed, ++ .start_ap = rtw_ops_start_ap, ++ .stop_ap = rtw_ops_stop_ap, + .conf_tx = rtw_ops_conf_tx, + .sta_add = rtw_ops_sta_add, + .sta_remove = rtw_ops_sta_remove, ++ .set_tim = rtw_ops_set_tim, + .set_key = rtw_ops_set_key, + .ampdu_action = rtw_ops_ampdu_action, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) + .can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu, ++#endif + .sw_scan_start = rtw_ops_sw_scan_start, + .sw_scan_complete = rtw_ops_sw_scan_complete, + .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, +@@ -824,6 +1015,12 @@ const struct ieee80211_ops rtw_ops = { + .set_antenna = rtw_ops_set_antenna, + .get_antenna = rtw_ops_get_antenna, + .reconfig_complete = rtw_reconfig_complete, ++ .hw_scan = rtw_ops_hw_scan, ++ .cancel_hw_scan = rtw_ops_cancel_hw_scan, ++ .sta_rc_update = rtw_ops_sta_rc_update, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ .set_sar_specs = rtw_ops_set_sar_specs, ++#endif + #ifdef CONFIG_PM + .suspend = rtw_ops_suspend, + .resume = rtw_ops_resume, +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 2ef1416899f0..b2b430ff93be 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -2,6 +2,8 @@ + /* Copyright(c) 2018-2019 Realtek Corporation + */ + ++#include ++ + #include "main.h" + #include "regd.h" + #include "fw.h" +@@ -15,18 +17,28 @@ + #include "tx.h" + #include "debug.h" + #include "bf.h" ++#include "sar.h" ++#include "sdio.h" + +-unsigned int rtw_fw_lps_deep_mode; +-EXPORT_SYMBOL(rtw_fw_lps_deep_mode); ++bool rtw_disable_lps_deep_mode; ++EXPORT_SYMBOL(rtw_disable_lps_deep_mode); + bool rtw_bf_support = true; + unsigned int rtw_debug_mask; + EXPORT_SYMBOL(rtw_debug_mask); ++/* EDCCA is enabled during normal behavior. For debugging purpose in ++ * a noisy environment, it can be disabled via edcca debugfs. Because ++ * all rtw88 devices will probably be affected if environment is noisy, ++ * rtw_edcca_enabled is just declared by driver instead of by device. ++ * So, turning it off will take effect for all rtw88 devices before ++ * there is a tough reason to maintain rtw_edcca_enabled by device. ++ */ ++bool rtw_edcca_enabled = true; + +-module_param_named(lps_deep_mode, rtw_fw_lps_deep_mode, uint, 0644); ++module_param_named(disable_lps_deep, rtw_disable_lps_deep_mode, bool, 0644); + module_param_named(support_bf, rtw_bf_support, bool, 0644); + module_param_named(debug_mask, rtw_debug_mask, uint, 0644); + +-MODULE_PARM_DESC(lps_deep_mode, "Deeper PS mode. If 0, deep PS is disabled"); ++MODULE_PARM_DESC(disable_lps_deep, "Set Y to disable Deep PS"); + MODULE_PARM_DESC(support_bf, "Set Y to enable beamformee support"); + MODULE_PARM_DESC(debug_mask, "Debugging mask"); + +@@ -67,6 +79,7 @@ static struct ieee80211_channel rtw_channeltable_5g[] = { + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, ++ {.center_freq = 5720, .hw_value = 144,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, +@@ -90,6 +103,26 @@ static struct ieee80211_rate rtw_ratetable[] = { + {.bitrate = 540, .hw_value = 0x0b,}, + }; + ++static const struct ieee80211_iface_limit rtw_iface_limits[] = { ++ { ++ .max = 1, ++ .types = BIT(NL80211_IFTYPE_STATION), ++ }, ++ { ++ .max = 1, ++ .types = BIT(NL80211_IFTYPE_AP), ++ } ++}; ++ ++static const struct ieee80211_iface_combination rtw_iface_combs[] = { ++ { ++ .limits = rtw_iface_limits, ++ .n_limits = ARRAY_SIZE(rtw_iface_limits), ++ .max_interfaces = 2, ++ .num_different_channels = 1, ++ } ++}; ++ + u16 rtw_desc_to_bitrate(u8 desc_rate) + { + struct ieee80211_rate rate; +@@ -152,14 +185,17 @@ static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) + bf_info->cur_csi_rpt_rate = new_csi_rate_idx; + } + +-static void rtw_vif_watch_dog_iter(void *data, u8 *mac, +- struct ieee80211_vif *vif) ++static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) + { + struct rtw_watch_dog_iter_data *iter_data = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ if (vif->cfg.assoc) ++#else + if (vif->bss_conf.assoc) ++#endif + iter_data->rtwvif = rtwvif; + + rtw_dynamic_csi_rate(iter_data->rtwdev, rtwvif); +@@ -195,8 +231,11 @@ static void rtw_watch_dog_work(struct work_struct *work) + else + clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); + ++ rtw_coex_wl_status_check(rtwdev); ++ rtw_coex_query_bt_hid_list(rtwdev); ++ + if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags)) +- rtw_coex_wl_status_change_notify(rtwdev); ++ rtw_coex_wl_status_change_notify(rtwdev, 0); + + if (stats->tx_cnt > RTW_LPS_THRESHOLD || + stats->rx_cnt > RTW_LPS_THRESHOLD) +@@ -226,19 +265,22 @@ static void rtw_watch_dog_work(struct work_struct *work) + rtw_phy_dynamic_mechanism(rtwdev); + + data.rtwdev = rtwdev; +- /* use atomic version to avoid taking local->iflist_mtx mutex */ +- rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data); ++ /* rtw_iterate_vifs internally uses an atomic iterator which is needed ++ * to avoid taking local->iflist_mtx mutex ++ */ ++ rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); + + /* fw supports only one station associated to enter lps, if there are + * more than two stations associated to the AP, then we can not enter + * lps, because fw does not handle the overlapped beacon interval + * +- * mac80211 should iterate vifs and determine if driver can enter +- * ps by passing IEEE80211_CONF_PS to us, all we need to do is to ++ * rtw_recalc_lps() iterate vifs and determine if driver can enter ++ * ps by vif->type and vif->cfg.ps, all we need to do here is to + * get that vif and check if device is having traffic more than the + * threshold. + */ +- if (rtwdev->ps_enabled && data.rtwvif && !ps_active) ++ if (rtwdev->ps_enabled && data.rtwvif && !ps_active && ++ !rtwdev->beacon_loss && !rtwdev->ap_active) + rtw_enter_lps(rtwdev, data.rtwvif->port); + + rtwdev->watch_dog_cnt++; +@@ -259,6 +301,16 @@ static void rtw_c2h_work(struct work_struct *work) + } + } + ++static void rtw_ips_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ips_work); ++ ++ mutex_lock(&rtwdev->mutex); ++ if (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE) ++ rtw_enter_ips(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++} ++ + static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) + { + unsigned long mac_id; +@@ -270,29 +322,50 @@ static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) + return mac_id; + } + ++static void rtw_sta_rc_work(struct work_struct *work) ++{ ++ struct rtw_sta_info *si = container_of(work, struct rtw_sta_info, ++ rc_work); ++ struct rtw_dev *rtwdev = si->rtwdev; ++ ++ mutex_lock(&rtwdev->mutex); ++ rtw_update_sta_info(rtwdev, si, true); ++ mutex_unlock(&rtwdev->mutex); ++} ++ + int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + struct ieee80211_vif *vif) + { + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; ++ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + int i; + + si->mac_id = rtw_acquire_macid(rtwdev); + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) + return -ENOSPC; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0) ++#else ++ if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc == 0) ++#endif ++ rtwvif->mac_id = si->mac_id; ++ si->rtwdev = rtwdev; + si->sta = sta; + si->vif = vif; + si->init_ra_lv = 1; + ewma_rssi_init(&si->avg_rssi); + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw_txq_init(rtwdev, sta->txq[i]); ++ INIT_WORK(&si->rc_work, rtw_sta_rc_work); + +- rtw_update_sta_info(rtwdev, si); ++ rtw_update_sta_info(rtwdev, si, true); + rtw_fw_media_status_report(rtwdev, si->mac_id, true); + + rtwdev->sta_cnt++; +- rtw_info(rtwdev, "sta %pM joined with macid %d\n", +- sta->addr, si->mac_id); ++ rtwdev->beacon_loss = false; ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "sta %pM joined with macid %d\n", ++ sta->addr, si->mac_id); + + return 0; + } +@@ -303,6 +376,8 @@ void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + int i; + ++ cancel_work_sync(&si->rc_work); ++ + rtw_release_macid(rtwdev, si->mac_id); + if (fw_exist) + rtw_fw_media_status_report(rtwdev, si->mac_id, false); +@@ -313,65 +388,203 @@ void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + kfree(si->mask); + + rtwdev->sta_cnt--; +- rtw_info(rtwdev, "sta %pM with macid %d left\n", +- sta->addr, si->mac_id); ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "sta %pM with macid %d left\n", ++ sta->addr, si->mac_id); ++} ++ ++struct rtw_fwcd_hdr { ++ u32 item; ++ u32 size; ++ u32 padding1; ++ u32 padding2; ++} __packed; ++ ++static int rtw_fwcd_prep(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_fwcd_desc *desc = &rtwdev->fw.fwcd_desc; ++ const struct rtw_fwcd_segs *segs = chip->fwcd_segs; ++ u32 prep_size = chip->fw_rxff_size + sizeof(struct rtw_fwcd_hdr); ++ u8 i; ++ ++ if (segs) { ++ prep_size += segs->num * sizeof(struct rtw_fwcd_hdr); ++ ++ for (i = 0; i < segs->num; i++) ++ prep_size += segs->segs[i]; ++ } ++ ++ desc->data = vmalloc(prep_size); ++ if (!desc->data) ++ return -ENOMEM; ++ ++ desc->size = prep_size; ++ desc->next = desc->data; ++ ++ return 0; ++} ++ ++static u8 *rtw_fwcd_next(struct rtw_dev *rtwdev, u32 item, u32 size) ++{ ++ struct rtw_fwcd_desc *desc = &rtwdev->fw.fwcd_desc; ++ struct rtw_fwcd_hdr *hdr; ++ u8 *next; ++ ++ if (!desc->data) { ++ rtw_dbg(rtwdev, RTW_DBG_FW, "fwcd isn't prepared successfully\n"); ++ return NULL; ++ } ++ ++ next = desc->next + sizeof(struct rtw_fwcd_hdr); ++ if (next - desc->data + size > desc->size) { ++ rtw_dbg(rtwdev, RTW_DBG_FW, "fwcd isn't prepared enough\n"); ++ return NULL; ++ } ++ ++ hdr = (struct rtw_fwcd_hdr *)(desc->next); ++ hdr->item = item; ++ hdr->size = size; ++ hdr->padding1 = 0x01234567; ++ hdr->padding2 = 0x89abcdef; ++ desc->next = next + size; ++ ++ return next; ++} ++ ++static void rtw_fwcd_dump(struct rtw_dev *rtwdev) ++{ ++ struct rtw_fwcd_desc *desc = &rtwdev->fw.fwcd_desc; ++ ++ rtw_dbg(rtwdev, RTW_DBG_FW, "dump fwcd\n"); ++ ++ /* Data will be freed after lifetime of device coredump. After calling ++ * dev_coredump, data is supposed to be handled by the device coredump ++ * framework. Note that a new dump will be discarded if a previous one ++ * hasn't been released yet. ++ */ ++ dev_coredumpv(rtwdev->dev, desc->data, desc->size, GFP_KERNEL); + } + +-static bool rtw_fw_dump_crash_log(struct rtw_dev *rtwdev) ++static void rtw_fwcd_free(struct rtw_dev *rtwdev, bool free_self) ++{ ++ struct rtw_fwcd_desc *desc = &rtwdev->fw.fwcd_desc; ++ ++ if (free_self) { ++ rtw_dbg(rtwdev, RTW_DBG_FW, "free fwcd by self\n"); ++ vfree(desc->data); ++ } ++ ++ desc->data = NULL; ++ desc->next = NULL; ++} ++ ++static int rtw_fw_dump_crash_log(struct rtw_dev *rtwdev) + { + u32 size = rtwdev->chip->fw_rxff_size; + u32 *buf; + u8 seq; +- bool ret = true; + +- buf = vmalloc(size); ++ buf = (u32 *)rtw_fwcd_next(rtwdev, RTW_FWCD_TLV, size); + if (!buf) +- goto exit; ++ return -ENOMEM; + + if (rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RXBUF_FW, 0, size, buf)) { + rtw_dbg(rtwdev, RTW_DBG_FW, "dump fw fifo fail\n"); +- goto free_buf; ++ return -EINVAL; + } + + if (GET_FW_DUMP_LEN(buf) == 0) { + rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's length is 0\n"); +- goto free_buf; ++ return -EINVAL; + } + + seq = GET_FW_DUMP_SEQ(buf); +- if (seq > 0 && seq != (rtwdev->fw.prev_dump_seq + 1)) { ++ if (seq > 0) { + rtw_dbg(rtwdev, RTW_DBG_FW, + "fw crash dump's seq is wrong: %d\n", seq); +- goto free_buf; ++ return -EINVAL; + } +- if (seq == 0 && +- (GET_FW_DUMP_TLV_TYPE(buf) != FW_CD_TYPE || +- GET_FW_DUMP_TLV_LEN(buf) != FW_CD_LEN || +- GET_FW_DUMP_TLV_VAL(buf) != FW_CD_VAL)) { +- rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's tlv is wrong\n"); +- goto free_buf; ++ ++ return 0; ++} ++ ++int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size, ++ u32 fwcd_item) ++{ ++ u32 rxff = rtwdev->chip->fw_rxff_size; ++ u32 dump_size, done_size = 0; ++ u8 *buf; ++ int ret; ++ ++ buf = rtw_fwcd_next(rtwdev, fwcd_item, size); ++ if (!buf) ++ return -ENOMEM; ++ ++ while (size) { ++ dump_size = size > rxff ? rxff : size; ++ ++ ret = rtw_ddma_to_fw_fifo(rtwdev, ocp_src + done_size, ++ dump_size); ++ if (ret) { ++ rtw_err(rtwdev, ++ "ddma fw 0x%x [+0x%x] to fw fifo fail\n", ++ ocp_src, done_size); ++ return ret; ++ } ++ ++ ret = rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RXBUF_FW, 0, ++ dump_size, (u32 *)(buf + done_size)); ++ if (ret) { ++ rtw_err(rtwdev, ++ "dump fw 0x%x [+0x%x] from fw fifo fail\n", ++ ocp_src, done_size); ++ return ret; ++ } ++ ++ size -= dump_size; ++ done_size += dump_size; + } + +- print_hex_dump_bytes("rtw88 fw dump: ", DUMP_PREFIX_OFFSET, buf, size); ++ return 0; ++} ++EXPORT_SYMBOL(rtw_dump_fw); ++ ++int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size) ++{ ++ u8 *buf; ++ u32 i; + +- if (GET_FW_DUMP_MORE(buf) == 1) { +- rtwdev->fw.prev_dump_seq = seq; +- ret = false; ++ if (addr & 0x3) { ++ WARN(1, "should be 4-byte aligned, addr = 0x%08x\n", addr); ++ return -EINVAL; + } + +-free_buf: +- vfree(buf); +-exit: +- rtw_write8(rtwdev, REG_MCU_TST_CFG, 0); ++ buf = rtw_fwcd_next(rtwdev, RTW_FWCD_REG, size); ++ if (!buf) ++ return -ENOMEM; + +- return ret; ++ for (i = 0; i < size; i += 4) ++ *(u32 *)(buf + i) = rtw_read32(rtwdev, addr + i); ++ ++ return 0; + } ++EXPORT_SYMBOL(rtw_dump_reg); + + void rtw_vif_assoc_changed(struct rtw_vif *rtwvif, + struct ieee80211_bss_conf *conf) + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ struct ieee80211_vif *vif = NULL; ++ ++ if (conf) ++ vif = container_of(conf, struct ieee80211_vif, bss_conf); ++ ++ if (conf && vif->cfg.assoc) { ++ rtwvif->aid = vif->cfg.aid; ++#else + if (conf && conf->assoc) { + rtwvif->aid = conf->aid; ++#endif + rtwvif->net_type = RTW_NET_MGD_LINKED; + } else { + rtwvif->aid = 0; +@@ -418,34 +631,46 @@ void rtw_fw_recovery(struct rtw_dev *rtwdev) + ieee80211_queue_work(rtwdev->hw, &rtwdev->fw_recovery_work); + } + +-static void rtw_fw_recovery_work(struct work_struct *work) ++static void __fw_recovery_work(struct rtw_dev *rtwdev) + { +- struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, +- fw_recovery_work); ++ int ret = 0; + +- /* rtw_fw_dump_crash_log() returns false indicates that there are +- * still more log to dump. Driver set 0x1cf[7:0] = 0x1 to tell firmware +- * to dump the remaining part of the log, and firmware will trigger an +- * IMR_C2HCMD interrupt to inform driver the log is ready. +- */ +- if (!rtw_fw_dump_crash_log(rtwdev)) { +- rtw_write8(rtwdev, REG_HRCV_MSG, 1); +- return; +- } +- rtwdev->fw.prev_dump_seq = 0; ++ set_bit(RTW_FLAG_RESTARTING, rtwdev->flags); ++ clear_bit(RTW_FLAG_RESTART_TRIGGERING, rtwdev->flags); + +- WARN(1, "firmware crash, start reset and recover\n"); ++ ret = rtw_fwcd_prep(rtwdev); ++ if (ret) ++ goto free; ++ ret = rtw_fw_dump_crash_log(rtwdev); ++ if (ret) ++ goto free; ++ ret = rtw_chip_dump_fw_crash(rtwdev); ++ if (ret) ++ goto free; + +- mutex_lock(&rtwdev->mutex); ++ rtw_fwcd_dump(rtwdev); ++free: ++ rtw_fwcd_free(rtwdev, !!ret); ++ rtw_write8(rtwdev, REG_MCU_TST_CFG, 0); ++ ++ WARN(1, "firmware crash, start reset and recover\n"); + +- set_bit(RTW_FLAG_RESTARTING, rtwdev->flags); + rcu_read_lock(); + rtw_iterate_keys_rcu(rtwdev, NULL, rtw_reset_key_iter, rtwdev); + rcu_read_unlock(); + rtw_iterate_stas_atomic(rtwdev, rtw_reset_sta_iter, rtwdev); + rtw_iterate_vifs_atomic(rtwdev, rtw_reset_vif_iter, rtwdev); ++ bitmap_zero(rtwdev->hw_port, RTW_PORT_NUM); + rtw_enter_ips(rtwdev); ++} ++ ++static void rtw_fw_recovery_work(struct work_struct *work) ++{ ++ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ++ fw_recovery_work); + ++ mutex_lock(&rtwdev->mutex); ++ __fw_recovery_work(rtwdev); + mutex_unlock(&rtwdev->mutex); + + ieee80211_restart_hw(rtwdev->hw); +@@ -485,67 +710,145 @@ static void rtw_txq_ba_work(struct work_struct *work) + rtw_iterate_stas_atomic(rtwdev, rtw_txq_ba_iter, &data); + } + ++void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel) ++{ ++ if (IS_CH_2G_BAND(channel)) ++ pkt_stat->band = NL80211_BAND_2GHZ; ++ else if (IS_CH_5G_BAND(channel)) ++ pkt_stat->band = NL80211_BAND_5GHZ; ++ else ++ return; ++ ++ pkt_stat->freq = ieee80211_channel_to_frequency(channel, pkt_stat->band); ++} ++EXPORT_SYMBOL(rtw_set_rx_freq_band); ++ ++void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period) ++{ ++ rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE); ++ rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1); ++} ++ ++void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel, ++ u8 primary_channel, enum rtw_supported_band band, ++ enum rtw_bandwidth bandwidth) ++{ ++ enum nl80211_band nl_band = rtw_hw_to_nl80211_band(band); ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 *cch_by_bw = hal->cch_by_bw; ++ u32 center_freq, primary_freq; ++ enum rtw_sar_bands sar_band; ++ u8 primary_channel_idx; ++ ++ center_freq = ieee80211_channel_to_frequency(center_channel, nl_band); ++ primary_freq = ieee80211_channel_to_frequency(primary_channel, nl_band); ++ ++ /* assign the center channel used while 20M bw is selected */ ++ cch_by_bw[RTW_CHANNEL_WIDTH_20] = primary_channel; ++ ++ /* assign the center channel used while current bw is selected */ ++ cch_by_bw[bandwidth] = center_channel; ++ ++ switch (bandwidth) { ++ case RTW_CHANNEL_WIDTH_20: ++ default: ++ primary_channel_idx = RTW_SC_DONT_CARE; ++ break; ++ case RTW_CHANNEL_WIDTH_40: ++ if (primary_freq > center_freq) ++ primary_channel_idx = RTW_SC_20_UPPER; ++ else ++ primary_channel_idx = RTW_SC_20_LOWER; ++ break; ++ case RTW_CHANNEL_WIDTH_80: ++ if (primary_freq > center_freq) { ++ if (primary_freq - center_freq == 10) ++ primary_channel_idx = RTW_SC_20_UPPER; ++ else ++ primary_channel_idx = RTW_SC_20_UPMOST; ++ ++ /* assign the center channel used ++ * while 40M bw is selected ++ */ ++ cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_channel + 4; ++ } else { ++ if (center_freq - primary_freq == 10) ++ primary_channel_idx = RTW_SC_20_LOWER; ++ else ++ primary_channel_idx = RTW_SC_20_LOWEST; ++ ++ /* assign the center channel used ++ * while 40M bw is selected ++ */ ++ cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_channel - 4; ++ } ++ break; ++ } ++ ++ switch (center_channel) { ++ case 1 ... 14: ++ sar_band = RTW_SAR_BAND_0; ++ break; ++ case 36 ... 64: ++ sar_band = RTW_SAR_BAND_1; ++ break; ++ case 100 ... 144: ++ sar_band = RTW_SAR_BAND_3; ++ break; ++ case 149 ... 177: ++ sar_band = RTW_SAR_BAND_4; ++ break; ++ default: ++ WARN(1, "unknown ch(%u) to SAR band\n", center_channel); ++ sar_band = RTW_SAR_BAND_0; ++ break; ++ } ++ ++ hal->current_primary_channel_index = primary_channel_idx; ++ hal->current_band_width = bandwidth; ++ hal->primary_channel = primary_channel; ++ hal->current_channel = center_channel; ++ hal->current_band_type = band; ++ hal->sar_band = sar_band; ++} ++ + void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *chan_params) + { + struct ieee80211_channel *channel = chandef->chan; + enum nl80211_chan_width width = chandef->width; +- u8 *cch_by_bw = chan_params->cch_by_bw; + u32 primary_freq, center_freq; + u8 center_chan; + u8 bandwidth = RTW_CHANNEL_WIDTH_20; +- u8 primary_chan_idx = 0; +- u8 i; + + center_chan = channel->hw_value; + primary_freq = channel->center_freq; + center_freq = chandef->center_freq1; + +- /* assign the center channel used while 20M bw is selected */ +- cch_by_bw[RTW_CHANNEL_WIDTH_20] = channel->hw_value; +- + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + bandwidth = RTW_CHANNEL_WIDTH_20; +- primary_chan_idx = RTW_SC_DONT_CARE; + break; + case NL80211_CHAN_WIDTH_40: + bandwidth = RTW_CHANNEL_WIDTH_40; +- if (primary_freq > center_freq) { +- primary_chan_idx = RTW_SC_20_UPPER; ++ if (primary_freq > center_freq) + center_chan -= 2; +- } else { +- primary_chan_idx = RTW_SC_20_LOWER; ++ else + center_chan += 2; +- } + break; + case NL80211_CHAN_WIDTH_80: + bandwidth = RTW_CHANNEL_WIDTH_80; + if (primary_freq > center_freq) { +- if (primary_freq - center_freq == 10) { +- primary_chan_idx = RTW_SC_20_UPPER; ++ if (primary_freq - center_freq == 10) + center_chan -= 2; +- } else { +- primary_chan_idx = RTW_SC_20_UPMOST; ++ else + center_chan -= 6; +- } +- /* assign the center channel used +- * while 40M bw is selected +- */ +- cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4; + } else { +- if (center_freq - primary_freq == 10) { +- primary_chan_idx = RTW_SC_20_LOWER; ++ if (center_freq - primary_freq == 10) + center_chan += 2; +- } else { +- primary_chan_idx = RTW_SC_20_LOWEST; ++ else + center_chan += 6; +- } +- /* assign the center channel used +- * while 40M bw is selected +- */ +- cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan - 4; + } + break; + default: +@@ -555,40 +858,33 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + + chan_params->center_chan = center_chan; + chan_params->bandwidth = bandwidth; +- chan_params->primary_chan_idx = primary_chan_idx; +- +- /* assign the center channel used while current bw is selected */ +- cch_by_bw[bandwidth] = center_chan; +- +- for (i = bandwidth + 1; i <= RTW_MAX_CHANNEL_WIDTH; i++) +- cch_by_bw[i] = 0; ++ chan_params->primary_chan = channel->hw_value; + } + + void rtw_set_channel(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_channel_params ch_param; +- u8 center_chan, bandwidth, primary_chan_idx; +- u8 i; ++ u8 center_chan, primary_chan, bandwidth, band; + + rtw_get_channel_params(&hw->conf.chandef, &ch_param); + if (WARN(ch_param.center_chan == 0, "Invalid channel\n")) + return; + + center_chan = ch_param.center_chan; ++ primary_chan = ch_param.primary_chan; + bandwidth = ch_param.bandwidth; +- primary_chan_idx = ch_param.primary_chan_idx; ++ band = ch_param.center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; + +- hal->current_band_width = bandwidth; +- hal->current_channel = center_chan; +- hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; ++ rtw_update_channel(rtwdev, center_chan, primary_chan, band, bandwidth); + +- for (i = RTW_CHANNEL_WIDTH_20; i <= RTW_MAX_CHANNEL_WIDTH; i++) +- hal->cch_by_bw[i] = ch_param.cch_by_bw[i]; ++ if (rtwdev->scan_info.op_chan) ++ rtw_store_op_chan(rtwdev, true); + +- chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx); ++ chip->ops->set_channel(rtwdev, center_chan, bandwidth, ++ hal->current_primary_channel_index); + + if (hal->current_band_type == RTW_BAND_5G) { + rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G); +@@ -611,7 +907,7 @@ void rtw_set_channel(struct rtw_dev *rtwdev) + + void rtw_chip_prepare_tx(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + if (rtwdev->need_rfk) { + rtwdev->need_rfk = false; +@@ -680,8 +976,8 @@ static u8 hw_bw_cap_to_bitamp(u8 bw_cap) + + static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; + + if (hw_ant_num == EFUSE_HW_CAP_IGNORE || + hw_ant_num >= hal->rf_path_num) +@@ -705,7 +1001,11 @@ static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) + static u64 get_vht_ra_mask(struct ieee80211_sta *sta) + { + u64 ra_mask = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); ++#else + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); ++#endif + u8 vht_mcs_cap; + int i, nss; + +@@ -825,37 +1125,52 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num) + #define RA_MASK_VHT_RATES (RA_MASK_VHT_RATES_1SS | \ + RA_MASK_VHT_RATES_2SS | \ + RA_MASK_VHT_RATES_3SS) ++#define RA_MASK_CCK_IN_BG 0x00005 + #define RA_MASK_CCK_IN_HT 0x00005 + #define RA_MASK_CCK_IN_VHT 0x00005 + #define RA_MASK_OFDM_IN_VHT 0x00010 + #define RA_MASK_OFDM_IN_HT_2G 0x00010 + #define RA_MASK_OFDM_IN_HT_5G 0x00030 + +-static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev, +- struct rtw_sta_info *si, +- u64 ra_mask, bool is_vht_enable, +- u8 wireless_set) ++static u64 rtw_rate_mask_rssi(struct rtw_sta_info *si, u8 wireless_set) ++{ ++ u8 rssi_level = si->rssi_level; ++ ++ if (wireless_set == WIRELESS_CCK) ++ return 0xffffffffffffffffULL; ++ ++ if (rssi_level == 0) ++ return 0xffffffffffffffffULL; ++ else if (rssi_level == 1) ++ return 0xfffffffffffffff0ULL; ++ else if (rssi_level == 2) ++ return 0xffffffffffffefe0ULL; ++ else if (rssi_level == 3) ++ return 0xffffffffffffcfc0ULL; ++ else if (rssi_level == 4) ++ return 0xffffffffffff8f80ULL; ++ else ++ return 0xffffffffffff0f00ULL; ++} ++ ++static u64 rtw_rate_mask_recover(u64 ra_mask, u64 ra_mask_bak) ++{ ++ if ((ra_mask & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)) == 0) ++ ra_mask |= (ra_mask_bak & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)); ++ ++ if (ra_mask == 0) ++ ra_mask |= (ra_mask_bak & (RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)); ++ ++ return ra_mask; ++} ++ ++static u64 rtw_rate_mask_cfg(struct rtw_dev *rtwdev, struct rtw_sta_info *si, ++ u64 ra_mask, bool is_vht_enable) + { + struct rtw_hal *hal = &rtwdev->hal; + const struct cfg80211_bitrate_mask *mask = si->mask; + u64 cfg_mask = GENMASK_ULL(63, 0); +- u8 rssi_level, band; +- +- if (wireless_set != WIRELESS_CCK) { +- rssi_level = si->rssi_level; +- if (rssi_level == 0) +- ra_mask &= 0xffffffffffffffffULL; +- else if (rssi_level == 1) +- ra_mask &= 0xfffffffffffffff0ULL; +- else if (rssi_level == 2) +- ra_mask &= 0xffffffffffffefe0ULL; +- else if (rssi_level == 3) +- ra_mask &= 0xffffffffffffcfc0ULL; +- else if (rssi_level == 4) +- ra_mask &= 0xffffffffffff8f80ULL; +- else if (rssi_level >= 5) +- ra_mask &= 0xffffffffffff0f00ULL; +- } ++ u8 band; + + if (!si->use_cfg_mask) + return ra_mask; +@@ -891,8 +1206,10 @@ static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev, + return ra_mask; + } + +-void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) ++void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, ++ bool reset_ra_mask) + { ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct ieee80211_sta *sta = si->sta; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_hal *hal = &rtwdev->hal; +@@ -904,16 +1221,38 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + u8 ldpc_en = 0; + u8 tx_num = 1; + u64 ra_mask = 0; ++ u64 ra_mask_bak = 0; + bool is_vht_enable = false; + bool is_support_sgi = false; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.vht_supported) { ++#else + if (sta->vht_cap.vht_supported) { ++#endif + is_vht_enable = true; + ra_mask |= get_vht_ra_mask(sta); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) ++#else + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) ++#endif + stbc_en = VHT_STBC_EN; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) ++#else + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) ++#endif + ldpc_en = VHT_LDPC_EN; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ } else if (sta->deflink.ht_cap.ht_supported) { ++ ra_mask |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20) | ++ (sta->deflink.ht_cap.mcs.rx_mask[0] << 12); ++ if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) ++ stbc_en = HT_STBC_EN; ++ if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) ++ ldpc_en = HT_LDPC_EN; ++#else + } else if (sta->ht_cap.ht_supported) { + ra_mask |= (sta->ht_cap.mcs.rx_mask[1] << 20) | + (sta->ht_cap.mcs.rx_mask[0] << 12); +@@ -921,91 +1260,157 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + stbc_en = HT_STBC_EN; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + ldpc_en = HT_LDPC_EN; ++#endif + } + +- if (efuse->hw_cap.nss == 1) ++ if (efuse->hw_cap.nss == 1 || rtwdev->hal.txrx_1ss) + ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; + + if (hal->current_band_type == RTW_BAND_5G) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; ++#else + ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; ++#endif ++ ra_mask_bak = ra_mask; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.vht_supported) { ++#else + if (sta->vht_cap.vht_supported) { ++#endif + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_OFDM | WIRELESS_VHT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ } else if (sta->deflink.ht_cap.ht_supported) { ++#else + } else if (sta->ht_cap.ht_supported) { ++#endif + ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G; + wireless_set = WIRELESS_OFDM | WIRELESS_HT; + } else { + wireless_set = WIRELESS_OFDM; + } ++ dm_info->rrsr_val_init = RRSR_INIT_5G; + } else if (hal->current_band_type == RTW_BAND_2G) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ]; ++#else + ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; ++#endif ++ ra_mask_bak = ra_mask; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.vht_supported) { ++#else + if (sta->vht_cap.vht_supported) { ++#endif + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT | + RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT | WIRELESS_VHT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ } else if (sta->deflink.ht_cap.ht_supported) { ++#else + } else if (sta->ht_cap.ht_supported) { ++#endif + ra_mask &= RA_MASK_HT_RATES | RA_MASK_CCK_IN_HT | + RA_MASK_OFDM_IN_HT_2G; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ } else if (sta->deflink.supp_rates[0] <= 0xf) { ++#else + } else if (sta->supp_rates[0] <= 0xf) { ++#endif + wireless_set = WIRELESS_CCK; + } else { ++ ra_mask &= RA_MASK_OFDM_RATES | RA_MASK_CCK_IN_BG; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM; + } ++ dm_info->rrsr_val_init = RRSR_INIT_2G; + } else { + rtw_err(rtwdev, "Unknown band type\n"); ++ ra_mask_bak = ra_mask; + wireless_set = 0; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ switch (sta->deflink.bandwidth) { ++#else + switch (sta->bandwidth) { ++#endif + case IEEE80211_STA_RX_BW_80: + bw_mode = RTW_CHANNEL_WIDTH_80; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ is_support_sgi = sta->deflink.vht_cap.vht_supported && ++ (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); ++#else + is_support_sgi = sta->vht_cap.vht_supported && + (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); ++#endif + break; + case IEEE80211_STA_RX_BW_40: + bw_mode = RTW_CHANNEL_WIDTH_40; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ is_support_sgi = sta->deflink.ht_cap.ht_supported && ++ (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40); ++#else + is_support_sgi = sta->ht_cap.ht_supported && + (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); ++#endif + break; + default: + bw_mode = RTW_CHANNEL_WIDTH_20; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ is_support_sgi = sta->deflink.ht_cap.ht_supported && ++ (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20); ++#else + is_support_sgi = sta->ht_cap.ht_supported && + (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); ++#endif + break; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) { ++#else + if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { ++#endif + tx_num = 2; + rf_type = RF_2T2R; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ } else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) { ++#else + } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { ++#endif + tx_num = 2; + rf_type = RF_2T2R; + } + + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); + +- ra_mask = rtw_update_rate_mask(rtwdev, si, ra_mask, is_vht_enable, +- wireless_set); ++ ra_mask &= rtw_rate_mask_rssi(si, wireless_set); ++ ra_mask = rtw_rate_mask_recover(ra_mask, ra_mask_bak); ++ ra_mask = rtw_rate_mask_cfg(rtwdev, si, ra_mask, is_vht_enable); + + si->bw_mode = bw_mode; + si->stbc_en = stbc_en; + si->ldpc_en = ldpc_en; + si->rf_type = rf_type; +- si->wireless_set = wireless_set; + si->sgi_enable = is_support_sgi; + si->vht_enable = is_vht_enable; + si->ra_mask = ra_mask; + si->rate_id = rate_id; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++ rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask); ++#else + rtw_fw_send_ra_info(rtwdev, si); ++#endif + } + + static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw; + + fw = &rtwdev->fw; +@@ -1023,9 +1428,29 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) + return 0; + } + ++static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, ++ struct rtw_fw_state *fw) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ if (rtw_disable_lps_deep_mode || !chip->lps_deep_mode_supported || ++ !fw->feature) ++ return LPS_DEEP_MODE_NONE; ++ ++ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_PG)) && ++ rtw_fw_feature_check(fw, FW_FEATURE_PG)) ++ return LPS_DEEP_MODE_PG; ++ ++ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_LCLK)) && ++ rtw_fw_feature_check(fw, FW_FEATURE_LCLK)) ++ return LPS_DEEP_MODE_LCLK; ++ ++ return LPS_DEEP_MODE_NONE; ++} ++ + static int rtw_power_on(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw = &rtwdev->fw; + bool wifi_only; + int ret; +@@ -1087,6 +1512,73 @@ static int rtw_power_on(struct rtw_dev *rtwdev) + return ret; + } + ++void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start) ++{ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_NOTIFY_SCAN)) ++ return; ++ ++ if (start) { ++ rtw_fw_scan_notify(rtwdev, true); ++ } else { ++ reinit_completion(&rtwdev->fw_scan_density); ++ rtw_fw_scan_notify(rtwdev, false); ++ if (!wait_for_completion_timeout(&rtwdev->fw_scan_density, ++ SCAN_NOTIFY_TIMEOUT)) ++ rtw_warn(rtwdev, "firmware failed to report density after scan\n"); ++ } ++} ++ ++void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ++ const u8 *mac_addr, bool hw_scan) ++{ ++ u32 config = 0; ++ int ret = 0; ++ ++ rtw_leave_lps(rtwdev); ++ ++ if (hw_scan && (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE)) { ++ ret = rtw_leave_ips(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to leave idle state\n"); ++ return; ++ } ++ } ++ ++ ether_addr_copy(rtwvif->mac_addr, mac_addr); ++ config |= PORT_SET_MAC_ADDR; ++ rtw_vif_port_config(rtwdev, rtwvif, config); ++ ++ rtw_coex_scan_notify(rtwdev, COEX_SCAN_START); ++ rtw_core_fw_scan_notify(rtwdev, true); ++ ++ set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags); ++ set_bit(RTW_FLAG_SCANNING, rtwdev->flags); ++} ++ ++void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool hw_scan) ++{ ++ struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL; ++ u32 config = 0; ++ ++ if (!rtwvif) ++ return; ++ ++ clear_bit(RTW_FLAG_SCANNING, rtwdev->flags); ++ clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags); ++ ++ rtw_core_fw_scan_notify(rtwdev, false); ++ ++ ether_addr_copy(rtwvif->mac_addr, vif->addr); ++ config |= PORT_SET_MAC_ADDR; ++ rtw_vif_port_config(rtwdev, rtwvif, config); ++ ++ rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH); ++ ++ if (hw_scan && (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE)) ++ ieee80211_queue_work(rtwdev->hw, &rtwdev->ips_work); ++} ++ + int rtw_core_start(struct rtw_dev *rtwdev) + { + int ret; +@@ -1097,6 +1589,9 @@ int rtw_core_start(struct rtw_dev *rtwdev) + + rtw_sec_enable_sec_engine(rtwdev); + ++ rtwdev->lps_conf.deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->fw); ++ rtwdev->lps_conf.wow_deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->wow_fw); ++ + /* rcr reset after powered on */ + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); + +@@ -1111,6 +1606,7 @@ int rtw_core_start(struct rtw_dev *rtwdev) + static void rtw_power_off(struct rtw_dev *rtwdev) + { + rtw_hci_stop(rtwdev); ++ rtw_coex_power_off_setting(rtwdev); + rtw_mac_power_off(rtwdev); + } + +@@ -1124,12 +1620,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev) + mutex_unlock(&rtwdev->mutex); + + cancel_work_sync(&rtwdev->c2h_work); ++ cancel_work_sync(&rtwdev->update_beacon_work); + cancel_delayed_work_sync(&rtwdev->watch_dog_work); + cancel_delayed_work_sync(&coex->bt_relink_work); + cancel_delayed_work_sync(&coex->bt_reenable_work); + cancel_delayed_work_sync(&coex->defreeze_work); + cancel_delayed_work_sync(&coex->wl_remain_work); + cancel_delayed_work_sync(&coex->bt_remain_work); ++ cancel_delayed_work_sync(&coex->wl_connecting_work); ++ cancel_delayed_work_sync(&coex->bt_multi_link_remain_work); ++ cancel_delayed_work_sync(&coex->wl_ccklock_work); + + mutex_lock(&rtwdev->mutex); + +@@ -1139,6 +1639,7 @@ void rtw_core_stop(struct rtw_dev *rtwdev) + static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_ht_cap *ht_cap) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + + ht_cap->ht_supported = true; +@@ -1149,13 +1650,15 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + + if (rtw_chip_has_rx_ldpc(rtwdev)) + ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING; ++ if (rtw_chip_has_tx_stbc(rtwdev)) ++ ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC; + + if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40)) + ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_DSSSCCK40 | + IEEE80211_HT_CAP_SGI_40; + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; +- ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; ++ ht_cap->ampdu_density = chip->ampdu_density; + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + if (efuse->hw_cap.nss > 1) { + ht_cap->mcs.rx_mask[0] = 0xFF; +@@ -1219,8 +1722,23 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + vht_cap->vht_mcs.tx_highest = highest; + } + ++static u16 rtw_get_max_scan_ie_len(struct rtw_dev *rtwdev) ++{ ++ u16 len; ++ ++ len = rtwdev->chip->max_scan_ie_len; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) && ++ rtwdev->chip->id == RTW_CHIP_TYPE_8822C) ++ len = IEEE80211_MAX_DATA_LEN; ++ else if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM)) ++ len -= RTW_OLD_PROBE_PG_CNT * TX_PAGE_SIZE; ++ ++ return len; ++} ++ + static void rtw_set_supported_band(struct ieee80211_hw *hw, +- struct rtw_chip_info *chip) ++ const struct rtw_chip_info *chip) + { + struct rtw_dev *rtwdev = hw->priv; + struct ieee80211_supported_band *sband; +@@ -1249,16 +1767,73 @@ static void rtw_set_supported_band(struct ieee80211_hw *hw, + + err_out: + rtw_err(rtwdev, "failed to set supported band\n"); +- kfree(sband); + } + + static void rtw_unset_supported_band(struct ieee80211_hw *hw, +- struct rtw_chip_info *chip) ++ const struct rtw_chip_info *chip) + { + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); + } + ++static void rtw_vif_smps_iter(void *data, u8 *mac, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw_dev *rtwdev = (struct rtw_dev *)data; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) ++#else ++ if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) ++#endif ++ return; ++ ++ if (rtwdev->hal.txrx_1ss) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ ieee80211_request_smps(vif, 0, IEEE80211_SMPS_STATIC); ++#else ++ ieee80211_request_smps(vif, IEEE80211_SMPS_STATIC); ++#endif ++ else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ ieee80211_request_smps(vif, 0, IEEE80211_SMPS_OFF); ++#else ++ ieee80211_request_smps(vif, IEEE80211_SMPS_OFF); ++#endif ++} ++ ++void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool txrx_1ss) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_hal *hal = &rtwdev->hal; ++ ++ if (!chip->ops->config_txrx_mode || rtwdev->hal.txrx_1ss == txrx_1ss) ++ return; ++ ++ rtwdev->hal.txrx_1ss = txrx_1ss; ++ if (txrx_1ss) ++ chip->ops->config_txrx_mode(rtwdev, BB_PATH_A, BB_PATH_A, false); ++ else ++ chip->ops->config_txrx_mode(rtwdev, hal->antenna_tx, ++ hal->antenna_rx, false); ++ rtw_iterate_vifs_atomic(rtwdev, rtw_vif_smps_iter, rtwdev); ++} ++ ++static void __update_firmware_feature(struct rtw_dev *rtwdev, ++ struct rtw_fw_state *fw) ++{ ++ u32 feature; ++ const struct rtw_fw_hdr *fw_hdr = ++ (const struct rtw_fw_hdr *)fw->firmware->data; ++ ++ feature = le32_to_cpu(fw_hdr->feature); ++ fw->feature = feature & FW_FEATURE_SIG ? feature : 0; ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C && ++ RTW_FW_SUIT_VER_CODE(rtwdev->fw) < RTW_FW_VER_CODE(9, 9, 13)) ++ fw->feature_ext |= FW_FEATURE_EXT_OLD_PAGE_NUM; ++} ++ + static void __update_firmware_info(struct rtw_dev *rtwdev, + struct rtw_fw_state *fw) + { +@@ -1269,6 +1844,8 @@ static void __update_firmware_info(struct rtw_dev *rtwdev, + fw->version = le16_to_cpu(fw_hdr->version); + fw->sub_version = fw_hdr->subversion; + fw->sub_index = fw_hdr->subindex; ++ ++ __update_firmware_feature(rtwdev, fw); + } + + static void __update_firmware_info_legacy(struct rtw_dev *rtwdev, +@@ -1307,7 +1884,8 @@ static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) + update_firmware_info(rtwdev, fw); + complete_all(&fw->completion); + +- rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n", ++ rtw_info(rtwdev, "%sFirmware version %u.%u.%u, H2C version %u\n", ++ fw->type == RTW_WOWLAN_FW ? "WOW " : "", + fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); + } + +@@ -1333,6 +1911,7 @@ static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type) + return -ENOENT; + } + ++ fw->type = type; + fw->rtwdev = rtwdev; + init_completion(&fw->completion); + +@@ -1348,16 +1927,23 @@ static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type) + + static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; +- int ret = 0; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtwdev->hci.rpwm_addr = 0x03d9; + rtwdev->hci.cpwm_addr = 0x03da; + break; ++ case RTW_HCI_TYPE_SDIO: ++ rtwdev->hci.rpwm_addr = REG_SDIO_HRPWM1; ++ rtwdev->hci.cpwm_addr = REG_SDIO_HCPWM1_V2; ++ break; ++ case RTW_HCI_TYPE_USB: ++ rtwdev->hci.rpwm_addr = 0xfe58; ++ rtwdev->hci.cpwm_addr = 0xfe57; ++ break; + default: + rtw_err(rtwdev, "unsupported hci type\n"); + return -EINVAL; +@@ -1389,7 +1975,7 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) + + hal->bfee_sts_cap = 3; + +- return ret; ++ return 0; + } + + static int rtw_chip_efuse_enable(struct rtw_dev *rtwdev) +@@ -1548,7 +2134,7 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) + if (!rfe_def) + return -ENODEV; + +- rtw_phy_setup_phy_cond(rtwdev, 0); ++ rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type); + + rtw_phy_init_tx_power(rtwdev); + rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); +@@ -1605,16 +2191,26 @@ static void rtw_stats_init(struct rtw_dev *rtwdev) + + int rtw_core_init(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + int ret; + + INIT_LIST_HEAD(&rtwdev->rsvd_page_list); + INIT_LIST_HEAD(&rtwdev->txqs); + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ setup_timer(&rtwdev->tx_report.purge_timer, ++ (void *)(long unsigned int)rtw_tx_report_purge_timer, ++ (long unsigned int)rtwdev); ++#else + timer_setup(&rtwdev->tx_report.purge_timer, + rtw_tx_report_purge_timer, 0); +- tasklet_setup(&rtwdev->tx_tasklet, rtw_tx_tasklet); ++#endif ++ rtwdev->tx_wq = alloc_workqueue("rtw_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); ++ if (!rtwdev->tx_wq) { ++ rtw_warn(rtwdev, "alloc_workqueue rtw_tx_wq failed\n"); ++ return -ENOMEM; ++ } + + INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); + INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work); +@@ -1622,31 +2218,34 @@ int rtw_core_init(struct rtw_dev *rtwdev) + INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work); + INIT_DELAYED_WORK(&coex->wl_remain_work, rtw_coex_wl_remain_work); + INIT_DELAYED_WORK(&coex->bt_remain_work, rtw_coex_bt_remain_work); ++ INIT_DELAYED_WORK(&coex->wl_connecting_work, rtw_coex_wl_connecting_work); ++ INIT_DELAYED_WORK(&coex->bt_multi_link_remain_work, ++ rtw_coex_bt_multi_link_remain_work); ++ INIT_DELAYED_WORK(&coex->wl_ccklock_work, rtw_coex_wl_ccklock_work); ++ INIT_WORK(&rtwdev->tx_work, rtw_tx_work); + INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); ++ INIT_WORK(&rtwdev->ips_work, rtw_ips_work); + INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work); ++ INIT_WORK(&rtwdev->update_beacon_work, rtw_fw_update_beacon_work); + INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work); + skb_queue_head_init(&rtwdev->c2h_queue); + skb_queue_head_init(&rtwdev->coex.queue); + skb_queue_head_init(&rtwdev->tx_report.queue); + +- spin_lock_init(&rtwdev->rf_lock); +- spin_lock_init(&rtwdev->h2c.lock); + spin_lock_init(&rtwdev->txq_lock); + spin_lock_init(&rtwdev->tx_report.q_lock); + + mutex_init(&rtwdev->mutex); +- mutex_init(&rtwdev->coex.mutex); + mutex_init(&rtwdev->hal.tx_power_mutex); + + init_waitqueue_head(&rtwdev->coex.wait); ++ init_completion(&rtwdev->lps_leave_check); ++ init_completion(&rtwdev->fw_scan_density); + + rtwdev->sec.total_cam_num = 32; + rtwdev->hal.current_channel = 1; ++ rtwdev->dm_info.fix_rate = U8_MAX; + set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); +- if (!(BIT(rtw_fw_lps_deep_mode) & chip->lps_deep_mode_supported)) +- rtwdev->lps_conf.deep_mode = LPS_DEEP_MODE_NONE; +- else +- rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode; + + rtw_stats_init(rtwdev); + +@@ -1658,7 +2257,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) + ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW); + if (ret) { + rtw_warn(rtwdev, "no firmware loaded\n"); +- return ret; ++ goto out; + } + + if (chip->wow_fw_name) { +@@ -1668,10 +2267,15 @@ int rtw_core_init(struct rtw_dev *rtwdev) + wait_for_completion(&rtwdev->fw.completion); + if (rtwdev->fw.firmware) + release_firmware(rtwdev->fw.firmware); +- return ret; ++ goto out; + } + } ++ + return 0; ++ ++out: ++ destroy_workqueue(rtwdev->tx_wq); ++ return ret; + } + EXPORT_SYMBOL(rtw_core_init); + +@@ -1690,9 +2294,16 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) + if (wow_fw->firmware) + release_firmware(wow_fw->firmware); + +- tasklet_kill(&rtwdev->tx_tasklet); ++ destroy_workqueue(rtwdev->tx_wq); ++# if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) ++ timer_delete_sync(&rtwdev->tx_report.purge_timer); ++# else ++ del_timer_sync(&rtwdev->tx_report.purge_timer); ++# endif + spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); + skb_queue_purge(&rtwdev->tx_report.queue); ++ skb_queue_purge(&rtwdev->coex.queue); ++ skb_queue_purge(&rtwdev->c2h_queue); + spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); + + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, +@@ -1702,7 +2313,6 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) + } + + mutex_destroy(&rtwdev->mutex); +- mutex_destroy(&rtwdev->coex.mutex); + mutex_destroy(&rtwdev->hal.tx_power_mutex); + } + EXPORT_SYMBOL(rtw_core_deinit); +@@ -1713,9 +2323,11 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + int max_tx_headroom = 0; + int ret; + +- /* TODO: USB & SDIO may need extra room? */ + max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz; + ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) ++ max_tx_headroom += RTW_SDIO_DATA_PTR_ALIGN; ++ + hw->extra_tx_headroom = max_tx_headroom; + hw->queues = IEEE80211_NUM_ACS; + hw->txq_data_size = sizeof(struct rtw_txq); +@@ -1733,6 +2345,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, TX_AMSDU); ++ ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +@@ -1745,8 +2358,17 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + WIPHY_FLAG_TDLS_EXTERNAL_SETUP; + + hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; ++ hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS; ++ hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { ++ hw->wiphy->iface_combinations = rtw_iface_combs; ++ hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs); ++ } + + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); ++ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SCAN_RANDOM_SN); ++ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); + + #ifdef CONFIG_PM + hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; +@@ -1755,7 +2377,15 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + rtw_set_supported_band(hw, rtwdev->chip); + SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); + +- rtw_regd_init(rtwdev, rtw_regd_notifier); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ hw->wiphy->sar_capa = &rtw_sar_capa; ++#endif ++ ++ ret = rtw_regd_init(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init regd\n"); ++ return ret; ++ } + + ret = ieee80211_register_hw(hw); + if (ret) { +@@ -1763,8 +2393,11 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + return ret; + } + +- if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2)) +- rtw_err(rtwdev, "regulatory_hint fail\n"); ++ ret = rtw_regd_hint(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to hint regd\n"); ++ return ret; ++ } + + rtw_debugfs_init(rtwdev); + +@@ -1777,13 +2410,139 @@ EXPORT_SYMBOL(rtw_register_hw); + + void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + ieee80211_unregister_hw(hw); + rtw_unset_supported_band(hw, chip); + } + EXPORT_SYMBOL(rtw_unregister_hw); + ++static ++void rtw_swap_reg_nbytes(struct rtw_dev *rtwdev, const struct rtw_hw_reg *reg1, ++ const struct rtw_hw_reg *reg2, u8 nbytes) ++{ ++ u8 i; ++ ++ for (i = 0; i < nbytes; i++) { ++ u8 v1 = rtw_read8(rtwdev, reg1->addr + i); ++ u8 v2 = rtw_read8(rtwdev, reg2->addr + i); ++ ++ rtw_write8(rtwdev, reg1->addr + i, v2); ++ rtw_write8(rtwdev, reg2->addr + i, v1); ++ } ++} ++ ++static ++void rtw_swap_reg_mask(struct rtw_dev *rtwdev, const struct rtw_hw_reg *reg1, ++ const struct rtw_hw_reg *reg2) ++{ ++ u32 v1, v2; ++ ++ v1 = rtw_read32_mask(rtwdev, reg1->addr, reg1->mask); ++ v2 = rtw_read32_mask(rtwdev, reg2->addr, reg2->mask); ++ rtw_write32_mask(rtwdev, reg2->addr, reg2->mask, v1); ++ rtw_write32_mask(rtwdev, reg1->addr, reg1->mask, v2); ++} ++ ++struct rtw_iter_port_switch_data { ++ struct rtw_dev *rtwdev; ++ struct rtw_vif *rtwvif_ap; ++}; ++ ++static void rtw_port_switch_iter(void *data, struct ieee80211_vif *vif) ++{ ++ struct rtw_iter_port_switch_data *iter_data = data; ++ struct rtw_dev *rtwdev = iter_data->rtwdev; ++ struct rtw_vif *rtwvif_target = (struct rtw_vif *)vif->drv_priv; ++ struct rtw_vif *rtwvif_ap = iter_data->rtwvif_ap; ++ const struct rtw_hw_reg *reg1, *reg2; ++ ++ if (rtwvif_target->port != RTW_PORT_0) ++ return; ++ ++ rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n", ++ rtwvif_ap->port, rtwvif_target->port); ++ ++ /* Leave LPS so the value swapped are not in PS mode */ ++ rtw_leave_lps(rtwdev); ++ ++ reg1 = &rtwvif_ap->conf->net_type; ++ reg2 = &rtwvif_target->conf->net_type; ++ rtw_swap_reg_mask(rtwdev, reg1, reg2); ++ ++ reg1 = &rtwvif_ap->conf->mac_addr; ++ reg2 = &rtwvif_target->conf->mac_addr; ++ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, ETH_ALEN); ++ ++ reg1 = &rtwvif_ap->conf->bssid; ++ reg2 = &rtwvif_target->conf->bssid; ++ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, ETH_ALEN); ++ ++ reg1 = &rtwvif_ap->conf->bcn_ctrl; ++ reg2 = &rtwvif_target->conf->bcn_ctrl; ++ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, 1); ++ ++ swap(rtwvif_target->port, rtwvif_ap->port); ++ swap(rtwvif_target->conf, rtwvif_ap->conf); ++ ++ rtw_fw_default_port(rtwdev, rtwvif_target); ++} ++ ++void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) ++{ ++ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; ++ struct rtw_iter_port_switch_data iter_data; ++ ++ if (vif->type != NL80211_IFTYPE_AP || rtwvif->port == RTW_PORT_0) ++ return; ++ ++ iter_data.rtwdev = rtwdev; ++ iter_data.rtwvif_ap = rtwvif; ++ rtw_iterate_vifs(rtwdev, rtw_port_switch_iter, &iter_data); ++} ++ ++static void rtw_check_sta_active_iter(void *data, struct ieee80211_vif *vif) ++{ ++ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; ++ bool *active = data; ++ ++ if (*active) ++ return; ++ ++ if (vif->type != NL80211_IFTYPE_STATION) ++ return; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++ if (vif->cfg.assoc || !is_zero_ether_addr(rtwvif->bssid)) ++#else ++ if (vif->bss_conf.assoc || !is_zero_ether_addr(rtwvif->bssid)) ++#endif ++ *active = true; ++} ++ ++bool rtw_core_check_sta_active(struct rtw_dev *rtwdev) ++{ ++ bool sta_active = false; ++ ++ rtw_iterate_vifs(rtwdev, rtw_check_sta_active_iter, &sta_active); ++ ++ return rtwdev->ap_active || sta_active; ++} ++ ++void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable) ++{ ++ if (!rtwdev->ap_active) ++ return; ++ ++ if (enable) { ++ rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); ++ rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); ++ } else { ++ rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); ++ rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); ++ } ++} ++ + MODULE_AUTHOR("Realtek Corporation"); + MODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); + MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 8ba0b0824ae9..d4714c5a5abc 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -5,21 +5,57 @@ + #ifndef __RTK_MAIN_H_ + #define __RTK_MAIN_H_ + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#include "compiler.h" ++#endif + #include + #include + #include + #include + #include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) + #include ++#else ++#include "bitfield.h" ++#endif + #include + #include ++#include + + #include "util.h" ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) ++#include ++#endif ++ ++#if !defined(RHEL_RELEASE_CODE) ++#define RHEL_RELEASE_CODE 0 ++#define RHEL_RELEASE_VERSION(a, b) a<<8 & b ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)) || defined(RHEL_RELEASE) && (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0)) ++/* see Documentation/timers/timers-howto.rst for the thresholds */ ++static inline void fsleep(unsigned long usecs) ++{ ++ if (usecs <= 10) ++ udelay(usecs); ++ else if (usecs <= 20000) ++ usleep_range(usecs, 2 * usecs); ++ else ++ msleep(DIV_ROUND_UP(usecs, 1000)); ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) ++#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS ++#endif + + #define RTW_MAX_MAC_ID_NUM 32 + #define RTW_MAX_SEC_CAM_NUM 32 + #define MAX_PG_CAM_BACKUP_NUM 8 + ++#define RTW_SCAN_MAX_SSIDS 4 ++ + #define RTW_MAX_PATTERN_NUM 12 + #define RTW_MAX_PATTERN_MASK_SIZE 16 + #define RTW_MAX_PATTERN_SIZE 128 +@@ -29,6 +65,7 @@ + #define RFREG_MASK 0xfffff + #define INV_RF_DATA 0xffffffff + #define TX_PAGE_SIZE_SHIFT 7 ++#define TX_PAGE_SIZE (1 << TX_PAGE_SIZE_SHIFT) + + #define RTW_CHANNEL_WIDTH_MAX 3 + #define RTW_RF_PATH_MAX 4 +@@ -36,9 +73,69 @@ + + #define RTW_TP_SHIFT 18 /* bytes/2s --> Mbps */ + ++#ifndef read_poll_timeout ++#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \ ++ sleep_before_read, args...) \ ++({ \ ++ u64 __timeout_us = (timeout_us); \ ++ unsigned long __sleep_us = (sleep_us); \ ++ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ ++ might_sleep_if((__sleep_us) != 0); \ ++ if (sleep_before_read && __sleep_us) \ ++ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ ++ for (;;) { \ ++ (val) = op(args); \ ++ if (cond) \ ++ break; \ ++ if (__timeout_us && \ ++ ktime_compare(ktime_get(), __timeout) > 0) { \ ++ (val) = op(args); \ ++ break; \ ++ } \ ++ if (__sleep_us) \ ++ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ ++ } \ ++ (cond) ? 0 : -ETIMEDOUT; \ ++}) ++#endif ++ ++#if !defined(IEEE80211_AMPDU_TX_START_IMMEDIATE) ++#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1 ++#endif ++ ++#if !defined(fallthrough) ++#define fallthrough do {} while (0) ++#endif ++ ++#ifndef read_poll_timeout_atomic ++#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \ ++ delay_before_read, args...) \ ++({ \ ++ u64 __timeout_us = (timeout_us); \ ++ unsigned long __delay_us = (delay_us); \ ++ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ ++ if (delay_before_read && __delay_us) \ ++ udelay(__delay_us); \ ++ for (;;) { \ ++ (val) = op(args); \ ++ if (cond) \ ++ break; \ ++ if (__timeout_us && \ ++ ktime_compare(ktime_get(), __timeout) > 0) { \ ++ (val) = op(args); \ ++ break; \ ++ } \ ++ if (__delay_us) \ ++ udelay(__delay_us); \ ++ } \ ++ (cond) ? 0 : -ETIMEDOUT; \ ++}) ++#endif ++ + extern bool rtw_bf_support; +-extern unsigned int rtw_fw_lps_deep_mode; ++extern bool rtw_disable_lps_deep_mode; + extern unsigned int rtw_debug_mask; ++extern bool rtw_edcca_enabled; + extern const struct ieee80211_ops rtw_ops; + + #define RTW_MAX_CHANNEL_NUM_2G 14 +@@ -78,14 +175,12 @@ struct rtw_hci { + IS_CH_5G_BAND_3(channel) || IS_CH_5G_BAND_4(channel)) + + enum rtw_supported_band { +- RTW_BAND_2G = 1 << 0, +- RTW_BAND_5G = 1 << 1, +- RTW_BAND_60G = 1 << 2, +- +- RTW_BAND_MAX, ++ RTW_BAND_2G = BIT(NL80211_BAND_2GHZ), ++ RTW_BAND_5G = BIT(NL80211_BAND_5GHZ), ++ RTW_BAND_60G = BIT(NL80211_BAND_60GHZ), + }; + +-/* now, support upto 80M bw */ ++/* now, support up to 80M bw */ + #define RTW_MAX_CHANNEL_WIDTH RTW_CHANNEL_WIDTH_80 + + enum rtw_bandwidth { +@@ -353,13 +448,15 @@ enum rtw_flags { + RTW_FLAG_RUNNING, + RTW_FLAG_FW_RUNNING, + RTW_FLAG_SCANNING, +- RTW_FLAG_INACTIVE_PS, ++ RTW_FLAG_POWERON, + RTW_FLAG_LEISURE_PS, + RTW_FLAG_LEISURE_PS_DEEP, + RTW_FLAG_DIG_DISABLE, + RTW_FLAG_BUSY_TRAFFIC, + RTW_FLAG_WOWLAN, + RTW_FLAG_RESTARTING, ++ RTW_FLAG_RESTART_TRIGGERING, ++ RTW_FLAG_FORCE_LOWEST_RATE, + + NUM_OF_RTW_FLAGS, + }; +@@ -390,6 +487,15 @@ enum rtw_snr { + RTW_SNR_NUM + }; + ++enum rtw_port { ++ RTW_PORT_0 = 0, ++ RTW_PORT_1 = 1, ++ RTW_PORT_2 = 2, ++ RTW_PORT_3 = 3, ++ RTW_PORT_4 = 4, ++ RTW_PORT_NUM ++}; ++ + enum rtw_wow_flags { + RTW_WOW_FLAG_EN_MAGIC_PKT, + RTW_WOW_FLAG_EN_REKEY_PKT, +@@ -497,20 +603,10 @@ struct rtw_txpwr_idx { + struct rtw_5g_txpwr_idx pwr_idx_5g; + }; + +-struct rtw_timer_list { +- struct timer_list timer; +- void (*function)(void *data); +- void *args; +-}; +- + struct rtw_channel_params { + u8 center_chan; ++ u8 primary_chan; + u8 bandwidth; +- u8 primary_chan_idx; +- /* center channel by different available bandwidth, +- * val of (bw > current bandwidth) is invalid +- */ +- u8 cch_by_bw[RTW_MAX_CHANNEL_WIDTH + 1]; + }; + + struct rtw_hw_reg { +@@ -543,6 +639,11 @@ struct rtw_rf_sipi_addr { + u32 lssi_read_pi; + }; + ++struct rtw_hw_reg_offset { ++ struct rtw_hw_reg hw_reg; ++ u8 offset; ++}; ++ + struct rtw_backup_info { + u8 len; + u32 reg; +@@ -569,6 +670,7 @@ struct rtw_tx_pkt_info { + u32 tx_pkt_size; + u8 offset; + u8 pkt_offset; ++ u8 tim_offset; + u8 mac_id; + u8 rate_id; + u8 rate; +@@ -620,9 +722,12 @@ struct rtw_rx_pkt_stat { + s8 rx_snr[RTW_RF_PATH_MAX]; + u8 rx_evm[RTW_RF_PATH_MAX]; + s8 cfo_tail[RTW_RF_PATH_MAX]; ++ u16 freq; ++ u8 band; + + struct rtw_sta_info *si; + struct ieee80211_vif *vif; ++ struct ieee80211_hdr *hdr; + }; + + DECLARE_EWMA(tp, 10, 2); +@@ -664,6 +769,7 @@ enum rtw_pwr_state { + struct rtw_lps_conf { + enum rtw_lps_mode mode; + enum rtw_lps_deep_mode deep_mode; ++ enum rtw_lps_deep_mode wow_deep_mode; + enum rtw_pwr_state state; + u8 awake_interval; + u8 rlbm; +@@ -714,15 +820,14 @@ struct rtw_ra_report { + + struct rtw_txq { + struct list_head list; +- + unsigned long flags; +- unsigned long last_push; + }; + + #define RTW_BC_MC_MACID 1 + DECLARE_EWMA(rssi, 10, 16); + + struct rtw_sta_info { ++ struct rtw_dev *rtwdev; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + +@@ -733,12 +838,10 @@ struct rtw_sta_info { + u8 rate_id; + enum rtw_bandwidth bw_mode; + enum rtw_rf_type rf_type; +- enum rtw_wireless_set wireless_set; + u8 stbc_en:2; + u8 ldpc_en:2; + bool sgi_enable; + bool vht_enable; +- bool updated; + u8 init_ra_lv; + u64 ra_mask; + +@@ -748,6 +851,8 @@ struct rtw_sta_info { + + bool use_cfg_mask; + struct cfg80211_bitrate_mask *mask; ++ ++ struct work_struct rc_work; + }; + + enum rtw_bfee_role { +@@ -781,6 +886,7 @@ struct rtw_bf_info { + struct rtw_vif { + enum rtw_net_type net_type; + u16 aid; ++ u8 mac_id; /* for STA mode only */ + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 port; +@@ -788,6 +894,8 @@ struct rtw_vif { + struct list_head rsvd_page_list; + struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; + const struct rtw_vif_port *conf; ++ struct cfg80211_scan_request *scan_req; ++ struct ieee80211_scan_ies *scan_ies; + + struct rtw_traffic_stats stats; + +@@ -796,12 +904,27 @@ struct rtw_vif { + + struct rtw_regulatory { + char alpha2[2]; +- u8 chplan; +- u8 txpwr_regd; ++ u8 txpwr_regd_2g; ++ u8 txpwr_regd_5g; ++}; ++ ++enum rtw_regd_state { ++ RTW_REGD_STATE_WORLDWIDE, ++ RTW_REGD_STATE_PROGRAMMED, ++ RTW_REGD_STATE_SETTING, ++ ++ RTW_REGD_STATE_NR, ++}; ++ ++struct rtw_regd { ++ enum rtw_regd_state state; ++ const struct rtw_regulatory *regulatory; ++ enum nl80211_dfs_regions dfs_region; + }; + + struct rtw_chip_ops { + int (*mac_init)(struct rtw_dev *rtwdev); ++ int (*dump_fw_crash)(struct rtw_dev *rtwdev); + void (*shutdown)(struct rtw_dev *rtwdev); + int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); + void (*phy_set_param)(struct rtw_dev *rtwdev); +@@ -834,6 +957,20 @@ struct rtw_chip_ops { + struct ieee80211_bss_conf *conf); + void (*cfg_csi_rate)(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate, + u8 fixrate_en, u8 *new_rate); ++ void (*adaptivity_init)(struct rtw_dev *rtwdev); ++ void (*adaptivity)(struct rtw_dev *rtwdev); ++ void (*cfo_init)(struct rtw_dev *rtwdev); ++ void (*cfo_track)(struct rtw_dev *rtwdev); ++ void (*config_tx_path)(struct rtw_dev *rtwdev, u8 tx_path, ++ enum rtw_bb_path tx_path_1ss, ++ enum rtw_bb_path tx_path_cck, ++ bool is_tx2_path); ++ void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path, ++ u8 rx_path, bool is_tx2_path); ++ /* for USB/SDIO only */ ++ void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc); + + /* for coex */ + void (*coex_set_init)(struct rtw_dev *rtwdev); +@@ -1041,6 +1178,7 @@ enum rtw_rfe_fem { + struct rtw_rfe_def { + const struct rtw_table *phy_pg_tbl; + const struct rtw_table *txpwr_lmt_tbl; ++ const struct rtw_table *agc_btg_tbl; + }; + + #define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \ +@@ -1048,6 +1186,12 @@ struct rtw_rfe_def { + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ + } + ++#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, btg) { \ ++ .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ ++ .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ ++ .agc_btg_tbl = &rtw ## chip ## _agc_btg_type ## btg ## _tbl, \ ++ } ++ + #define RTW_PWR_TRK_5G_1 0 + #define RTW_PWR_TRK_5G_2 1 + #define RTW_PWR_TRK_5G_3 2 +@@ -1094,6 +1238,15 @@ enum rtw_fw_fifo_sel { + RTW_FW_FIFO_MAX, + }; + ++enum rtw_fwcd_item { ++ RTW_FWCD_TLV, ++ RTW_FWCD_REG, ++ RTW_FWCD_ROM, ++ RTW_FWCD_IMEM, ++ RTW_FWCD_DMEM, ++ RTW_FWCD_EMEM, ++}; ++ + /* hardware configuration for each IC */ + struct rtw_chip_info { + struct rtw_chip_ops *ops; +@@ -1111,6 +1264,7 @@ struct rtw_chip_info { + u32 txff_size; + u32 rxff_size; + u32 fw_rxff_size; ++ u16 rsvd_drv_pg_num; + u8 band; + u8 page_size; + u8 csi_buf_pg_num; +@@ -1119,10 +1273,16 @@ struct rtw_chip_info { + u8 txgi_factor; + bool is_pwr_by_rate_dec; + bool rx_ldpc; ++ bool tx_stbc; + u8 max_power_index; ++ u8 ampdu_density; + + u16 fw_fifo_addr[RTW_FW_FIFO_MAX]; ++ const struct rtw_fwcd_segs *fwcd_segs; + ++ u8 default_1ss_tx_path; ++ ++ bool path_div_supported; + bool ht_supported; + bool vht_supported; + u8 lps_deep_mode_supported; +@@ -1162,18 +1322,22 @@ struct rtw_chip_info { + u8 bfer_su_max_num; + u8 bfer_mu_max_num; + ++ struct rtw_hw_reg_offset *edcca_th; ++ s8 l2h_th_ini_cs; ++ s8 l2h_th_ini_ad; ++ + const char *wow_fw_name; + const struct wiphy_wowlan_support *wowlan_stub; + const u8 max_sched_scan_ssids; +- +- /* for 8821c set channel */ +- u32 ch_param[3]; ++ const u16 max_scan_ie_len; + + /* coex paras */ + u32 coex_para_ver; + u8 bt_desired_ver; + bool scbd_support; + bool new_scbd10_def; /* true: fix 2M(8822c) */ ++ bool ble_hid_profile_support; ++ bool wl_mimo_ps_support; + u8 pstdma_type; /* 0: LPSoff, 1:LPSon */ + u8 bt_rssi_type; + u8 ant_isolation; +@@ -1198,6 +1362,7 @@ struct rtw_chip_info { + const struct coex_5g_afh_map *afh_5g; + const struct rtw_hw_reg *btg_reg; + const struct rtw_reg_domain *coex_info_hw_regs; ++ u32 wl_fw_desired_ver; + }; + + enum rtw_coex_bt_state_cnt { +@@ -1219,6 +1384,7 @@ enum rtw_coex_bt_state_cnt { + }; + + enum rtw_coex_wl_state_cnt { ++ COEX_CNT_WL_SCANAP, + COEX_CNT_WL_CONNPKT, + COEX_CNT_WL_COEXRUN, + COEX_CNT_WL_NOISY0, +@@ -1241,6 +1407,8 @@ struct rtw_coex_rfe { + bool wlg_at_btg; + }; + ++#define COEX_WL_TDMA_PARA_LENGTH 5 ++ + struct rtw_coex_dm { + bool cur_ps_tdma_on; + bool cur_wl_rx_low_gain_en; +@@ -1260,6 +1428,7 @@ struct rtw_coex_dm { + u32 cur_ant_pos_type; + u32 cur_switch_status; + u32 setting_tdma; ++ u8 fw_tdma_para[COEX_WL_TDMA_PARA_LENGTH]; + }; + + #define COEX_BTINFO_SRC_WL_FW 0x0 +@@ -1267,7 +1436,8 @@ struct rtw_coex_dm { + #define COEX_BTINFO_SRC_BT_ACT 0x2 + #define COEX_BTINFO_SRC_BT_IQK 0x3 + #define COEX_BTINFO_SRC_BT_SCBD 0x4 +-#define COEX_BTINFO_SRC_MAX 0x5 ++#define COEX_BTINFO_SRC_H2C60 0x5 ++#define COEX_BTINFO_SRC_MAX 0x6 + + #define COEX_INFO_FTP BIT(7) + #define COEX_INFO_A2DP BIT(6) +@@ -1278,6 +1448,43 @@ struct rtw_coex_dm { + #define COEX_INFO_SCO_ESCO BIT(1) + #define COEX_INFO_CONNECTION BIT(0) + #define COEX_BTINFO_LENGTH_MAX 10 ++#define COEX_BTINFO_LENGTH 7 ++ ++#define COEX_BT_HIDINFO_LIST 0x0 ++#define COEX_BT_HIDINFO_A 0x1 ++#define COEX_BT_HIDINFO_NAME 3 ++ ++#define COEX_BT_HIDINFO_LENGTH 6 ++#define COEX_BT_HIDINFO_HANDLE_NUM 4 ++#define COEX_BT_HIDINFO_C2H_HANDLE 0 ++#define COEX_BT_HIDINFO_C2H_VENDOR 1 ++#define COEX_BT_BLE_HANDLE_THRS 0x10 ++#define COEX_BT_HIDINFO_NOTCON 0xff ++ ++struct rtw_coex_hid { ++ u8 hid_handle; ++ u8 hid_vendor; ++ u8 hid_name[COEX_BT_HIDINFO_NAME]; ++ bool hid_info_completed; ++ bool is_game_hid; ++}; ++ ++struct rtw_coex_hid_handle_list { ++ u8 cmd_id; ++ u8 len; ++ u8 subid; ++ u8 handle_cnt; ++ u8 handle[COEX_BT_HIDINFO_HANDLE_NUM]; ++} __packed; ++ ++struct rtw_coex_hid_info_a { ++ u8 cmd_id; ++ u8 len; ++ u8 subid; ++ u8 handle; ++ u8 vendor; ++ u8 name[COEX_BT_HIDINFO_NAME]; ++} __packed; + + struct rtw_coex_stat { + bool bt_disabled; +@@ -1299,6 +1506,8 @@ struct rtw_coex_stat { + bool bt_fix_2M; + bool bt_setup_link; + bool bt_multi_link; ++ bool bt_multi_link_pre; ++ bool bt_multi_link_remain; + bool bt_a2dp_sink; + bool bt_a2dp_active; + bool bt_reenable; +@@ -1306,6 +1515,9 @@ struct rtw_coex_stat { + bool bt_init_scan; + bool bt_slave; + bool bt_418_hid_exist; ++ bool bt_ble_hid_exist; ++ bool bt_game_hid_exist; ++ bool bt_hid_handle_cnt; + bool bt_mailbox_reply; + + bool wl_under_lps; +@@ -1323,9 +1535,17 @@ struct rtw_coex_stat { + bool wl_cck_lock; + bool wl_cck_lock_pre; + bool wl_cck_lock_ever; ++ bool wl_connecting; ++ bool wl_slot_toggle; ++ bool wl_slot_toggle_change; /* if toggle to no-toggle */ ++ bool wl_mimo_ps; + + u32 bt_supported_version; + u32 bt_supported_feature; ++ u32 hi_pri_tx; ++ u32 hi_pri_rx; ++ u32 lo_pri_tx; ++ u32 lo_pri_rx; + u32 patch_ver; + u16 bt_reg_vendor_ae; + u16 bt_reg_vendor_ac; +@@ -1347,13 +1567,21 @@ struct rtw_coex_stat { + u8 bt_a2dp_bitpool; + u8 bt_iqk_state; + ++ u16 wl_beacon_interval; + u8 wl_noisy_level; + u8 wl_fw_dbg_info[10]; + u8 wl_fw_dbg_info_pre[10]; ++ u8 wl_rx_rate; ++ u8 wl_tx_rate; ++ u8 wl_rts_rx_rate; + u8 wl_coex_mode; ++ u8 wl_iot_peer; + u8 ampdu_max_time; + u8 wl_tput_dir; + ++ u8 wl_toggle_para[6]; ++ u8 wl_toggle_interval; ++ + u16 score_board; + u16 retry_limit; + +@@ -1363,13 +1591,17 @@ struct rtw_coex_stat { + /* counters to record wifi states */ + u32 cnt_wl[COEX_CNT_WL_MAX]; + ++ /* counters to record bt c2h data */ ++ u32 cnt_bt_info_c2h[COEX_BTINFO_SRC_MAX]; ++ + u32 darfrc; + u32 darfrch; ++ ++ struct rtw_coex_hid hid_info[COEX_BT_HIDINFO_HANDLE_NUM]; ++ struct rtw_coex_hid_handle_list hid_handle_list; + }; + + struct rtw_coex { +- /* protects coex info request section */ +- struct mutex mutex; + struct sk_buff_head queue; + wait_queue_head_t wait; + +@@ -1378,6 +1610,7 @@ struct rtw_coex { + bool freeze; + bool freerun; + bool wl_rf_off; ++ bool manual_control; + + struct rtw_coex_stat stat; + struct rtw_coex_dm dm; +@@ -1388,6 +1621,10 @@ struct rtw_coex { + struct delayed_work defreeze_work; + struct delayed_work wl_remain_work; + struct delayed_work bt_remain_work; ++ struct delayed_work wl_connecting_work; ++ struct delayed_work bt_multi_link_remain_work; ++ struct delayed_work wl_ccklock_work; ++ + }; + + #define DPK_RF_REG_NUM 7 +@@ -1454,6 +1691,60 @@ struct rtw_iqk_info { + } result; + }; + ++enum rtw_rf_band { ++ RF_BAND_2G_CCK, ++ RF_BAND_2G_OFDM, ++ RF_BAND_5G_L, ++ RF_BAND_5G_M, ++ RF_BAND_5G_H, ++ RF_BAND_MAX ++}; ++ ++#define RF_GAIN_NUM 11 ++#define RF_HW_OFFSET_NUM 10 ++ ++struct rtw_gapk_info { ++ u32 rf3f_bp[RF_BAND_MAX][RF_GAIN_NUM][RTW_RF_PATH_MAX]; ++ u32 rf3f_fs[RTW_RF_PATH_MAX][RF_GAIN_NUM]; ++ bool txgapk_bp_done; ++ s8 offset[RF_GAIN_NUM][RTW_RF_PATH_MAX]; ++ s8 fianl_offset[RF_GAIN_NUM][RTW_RF_PATH_MAX]; ++ u8 read_txgain; ++ u8 channel; ++}; ++ ++#define EDCCA_TH_L2H_IDX 0 ++#define EDCCA_TH_H2L_IDX 1 ++#define EDCCA_TH_L2H_LB 48 ++#define EDCCA_ADC_BACKOFF 12 ++#define EDCCA_IGI_BASE 50 ++#define EDCCA_IGI_L2H_DIFF 8 ++#define EDCCA_L2H_H2L_DIFF 7 ++#define EDCCA_L2H_H2L_DIFF_NORMAL 8 ++ ++enum rtw_edcca_mode { ++ RTW_EDCCA_NORMAL = 0, ++ RTW_EDCCA_ADAPTIVITY = 1, ++}; ++ ++struct rtw_cfo_track { ++ bool is_adjust; ++ u8 crystal_cap; ++ s32 cfo_tail[RTW_RF_PATH_MAX]; ++ s32 cfo_cnt[RTW_RF_PATH_MAX]; ++ u32 packet_count; ++ u32 packet_count_pre; ++}; ++ ++#define RRSR_INIT_2G 0x15f ++#define RRSR_INIT_5G 0x150 ++ ++enum rtw_dm_cap { ++ RTW_DM_CAP_NA, ++ RTW_DM_CAP_TXGAPK, ++ RTW_DM_CAP_NUM ++}; ++ + struct rtw_dm_info { + u32 cck_fa_cnt; + u32 ofdm_fa_cnt; +@@ -1483,7 +1774,10 @@ struct rtw_dm_info { + u8 cck_gi_u_bnd; + u8 cck_gi_l_bnd; + ++ u8 fix_rate; + u8 tx_rate; ++ u32 rrsr_val_init; ++ u32 rrsr_mask_min; + u8 thermal_avg[RTW_RF_PATH_MAX]; + u8 thermal_meter_k; + u8 thermal_meter_lck; +@@ -1502,6 +1796,7 @@ struct rtw_dm_info { + u8 dack_dck[RTW_RF_PATH_MAX][2][DACK_DCK_BACKUP_NUM]; + + struct rtw_dpk_info dpk_info; ++ struct rtw_cfo_track cfo_track; + + /* [bandwidth 0:20M/1:40M][number of path] */ + u8 cck_pd_lv[2][RTW_RF_PATH_MAX]; +@@ -1519,7 +1814,14 @@ struct rtw_dm_info { + struct ewma_evm ewma_evm[RTW_EVM_NUM]; + struct ewma_snr ewma_snr[RTW_SNR_NUM]; + ++ u32 dm_flags; /* enum rtw_dm_cap */ + struct rtw_iqk_info iqk; ++ struct rtw_gapk_info gapk; ++ bool is_bt_iqk_timeout; ++ ++ s8 l2h_th_ini; ++ enum rtw_edcca_mode edcca_mode; ++ u8 scan_density; + }; + + struct rtw_efuse { +@@ -1623,6 +1925,17 @@ struct rtw_fifo_conf { + const struct rtw_rqpn *rqpn; + }; + ++struct rtw_fwcd_desc { ++ u32 size; ++ u8 *next; ++ u8 *data; ++}; ++ ++struct rtw_fwcd_segs { ++ const u32 *segs; ++ u8 num; ++}; ++ + #define FW_CD_TYPE 0xffff + #define FW_CD_LEN 4 + #define FW_CD_VAL 0xaabbccdd +@@ -1630,11 +1943,41 @@ struct rtw_fw_state { + const struct firmware *firmware; + struct rtw_dev *rtwdev; + struct completion completion; ++ struct rtw_fwcd_desc fwcd_desc; + u16 version; + u8 sub_version; + u8 sub_index; + u16 h2c_version; +- u8 prev_dump_seq; ++ u32 feature; ++ u32 feature_ext; ++ enum rtw_fw_type type; ++}; ++ ++enum rtw_sar_sources { ++ RTW_SAR_SOURCE_NONE, ++ RTW_SAR_SOURCE_COMMON, ++}; ++ ++enum rtw_sar_bands { ++ RTW_SAR_BAND_0, ++ RTW_SAR_BAND_1, ++ /* RTW_SAR_BAND_2, not used now */ ++ RTW_SAR_BAND_3, ++ RTW_SAR_BAND_4, ++ ++ RTW_SAR_BAND_NR, ++}; ++ ++/* the union is reserved for other kinds of SAR sources ++ * which might not re-use same format with array common. ++ */ ++union rtw_sar_cfg { ++ s8 common[RTW_SAR_BAND_NR]; ++}; ++ ++struct rtw_sar { ++ enum rtw_sar_sources src; ++ union rtw_sar_cfg cfg[RTW_RF_PATH_MAX][RTW_RATE_SECTION_MAX]; + }; + + struct rtw_hal { +@@ -1644,12 +1987,16 @@ struct rtw_hal { + u8 cut_version; + u8 mp_chip; + u8 oem_id; ++ u8 pkg_type; + struct rtw_phy_cond phy_cond; ++ bool rfe_btg; + + u8 ps_mode; + u8 current_channel; ++ u8 current_primary_channel_index; + u8 current_band_width; + u8 current_band_type; ++ u8 primary_channel; + + /* center channel for different available bandwidth, + * val of (bw > current_band_width) is invalid +@@ -1663,6 +2010,7 @@ struct rtw_hal { + u32 antenna_tx; + u32 antenna_rx; + u8 bfee_sts_cap; ++ bool txrx_1ss; + + /* protect tx power section */ + struct mutex tx_power_mutex; +@@ -1684,6 +2032,45 @@ struct rtw_hal { + [RTW_MAX_CHANNEL_NUM_5G]; + s8 tx_pwr_tbl[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; ++ ++ enum rtw_sar_bands sar_band; ++ struct rtw_sar sar; ++ ++ /* for 8821c set channel */ ++ u32 ch_param[3]; ++}; ++ ++struct rtw_path_div { ++ enum rtw_bb_path current_tx_path; ++ u32 path_a_sum; ++ u32 path_b_sum; ++ u16 path_a_cnt; ++ u16 path_b_cnt; ++}; ++ ++struct rtw_chan_info { ++ int pri_ch_idx; ++ int action_id; ++ int bw; ++ u8 extra_info; ++ u8 channel; ++ u16 timeout; ++}; ++ ++struct rtw_chan_list { ++ u32 buf_size; ++ u32 ch_num; ++ u32 size; ++ u16 addr; ++}; ++ ++struct rtw_hw_scan_info { ++ struct ieee80211_vif *scanning_vif; ++ u8 probe_pg_size; ++ u8 op_pri_ch_idx; ++ u8 op_pri_ch; ++ u8 op_chan; ++ u8 op_bw; + }; + + struct rtw_dev { +@@ -1692,14 +2079,15 @@ struct rtw_dev { + + struct rtw_hci hci; + +- struct rtw_chip_info *chip; ++ struct rtw_hw_scan_info scan_info; ++ const struct rtw_chip_info *chip; + struct rtw_hal hal; + struct rtw_fifo_conf fifo; + struct rtw_fw_state fw; + struct rtw_efuse efuse; + struct rtw_sec_desc sec; + struct rtw_traffic_stats stats; +- struct rtw_regulatory regd; ++ struct rtw_regd regd; + struct rtw_bf_info bf_info; + + struct rtw_dm_info dm_info; +@@ -1708,9 +2096,6 @@ struct rtw_dev { + /* ensures exclusive access from mac80211 callbacks */ + struct mutex mutex; + +- /* read/write rf register */ +- spinlock_t rf_lock; +- + /* watch dog every 2 sec */ + struct delayed_work watch_dog_work; + u32 watch_dog_cnt; +@@ -1720,42 +2105,49 @@ struct rtw_dev { + /* c2h cmd queue & handler work */ + struct sk_buff_head c2h_queue; + struct work_struct c2h_work; ++ struct work_struct ips_work; + struct work_struct fw_recovery_work; ++ struct work_struct update_beacon_work; + + /* used to protect txqs list */ + spinlock_t txq_lock; + struct list_head txqs; +- struct tasklet_struct tx_tasklet; ++ struct workqueue_struct *tx_wq; ++ struct work_struct tx_work; + struct work_struct ba_work; + + struct rtw_tx_report tx_report; + + struct { +- /* incicate the mail box to use with fw */ ++ /* indicate the mail box to use with fw */ + u8 last_box_num; +- /* protect to send h2c to fw */ +- spinlock_t lock; + u32 seq; + } h2c; + + /* lps power state & handler work */ + struct rtw_lps_conf lps_conf; + bool ps_enabled; ++ bool beacon_loss; ++ struct completion lps_leave_check; + + struct dentry *debugfs; + + u8 sta_cnt; + u32 rts_threshold; + ++ DECLARE_BITMAP(hw_port, RTW_PORT_NUM); + DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM); + DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS); + + u8 mp_mode; ++ struct rtw_path_div dm_path_div; + + struct rtw_fw_state wow_fw; + struct rtw_wow_param wow; + + bool need_rfk; ++ struct completion fw_scan_density; ++ bool ap_active; + + /* hci related data, must be last */ + u8 priv[] __aligned(sizeof(void *)); +@@ -1821,11 +2213,40 @@ static inline bool rtw_chip_has_rx_ldpc(struct rtw_dev *rtwdev) + return rtwdev->chip->rx_ldpc; + } + ++static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev) ++{ ++ return rtwdev->chip->tx_stbc; ++} ++ + static inline void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) + { + clear_bit(mac_id, rtwdev->mac_id_map); + } + ++static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev) ++{ ++ if (rtwdev->chip->ops->dump_fw_crash) ++ return rtwdev->chip->ops->dump_fw_crash(rtwdev); ++ ++ return 0; ++} ++ ++static inline ++enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band) ++{ ++ switch (hw_band) { ++ default: ++ case RTW_BAND_2G: ++ return NL80211_BAND_2GHZ; ++ case RTW_BAND_5G: ++ return NL80211_BAND_5GHZ; ++ case RTW_BAND_60G: ++ return NL80211_BAND_60GHZ; ++ } ++} ++ ++void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel); ++void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period); + void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *ch_param); + bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); +@@ -1838,8 +2259,17 @@ void rtw_set_channel(struct rtw_dev *rtwdev); + void rtw_chip_prepare_tx(struct rtw_dev *rtwdev); + void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, + u32 config); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void rtw_tx_report_purge_timer(void *ctx); ++#else + void rtw_tx_report_purge_timer(struct timer_list *t); +-void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); ++#endif ++void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, ++ bool reset_ra_mask); ++void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ++ const u8 *mac_addr, bool hw_scan); ++void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ++ bool hw_scan); + int rtw_core_start(struct rtw_dev *rtwdev); + void rtw_core_stop(struct rtw_dev *rtwdev); + int rtw_chip_info_setup(struct rtw_dev *rtwdev); +@@ -1855,5 +2285,15 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + bool fw_exist); + void rtw_fw_recovery(struct rtw_dev *rtwdev); +- ++void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start); ++int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size, ++ u32 fwcd_item); ++int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size); ++void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool config_1ss); ++void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel, ++ u8 primary_channel, enum rtw_supported_band band, ++ enum rtw_bandwidth bandwidth); ++void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif); ++bool rtw_core_check_sta_active(struct rtw_dev *rtwdev); ++void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable); + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c +index 676d861aaf99..494cf63293f4 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.c ++++ b/drivers/net/wireless/realtek/rtw88/pci.c +@@ -30,7 +30,8 @@ static u32 rtw_pci_tx_queue_idx_addr[] = { + [RTW_TX_QUEUE_H2C] = RTK_PCI_TXBD_IDX_H2CQ, + }; + +-static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, u8 queue) ++static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, ++ enum rtw_tx_queue_type queue) + { + switch (queue) { + case RTW_TX_QUEUE_BCN: +@@ -88,13 +89,6 @@ static void rtw_pci_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) + writel(val, rtwpci->mmap + addr); + } + +-static inline void *rtw_pci_get_tx_desc(struct rtw_pci_tx_ring *tx_ring, u8 idx) +-{ +- int offset = tx_ring->r.desc_size * idx; +- +- return tx_ring->r.head + offset; +-} +- + static void rtw_pci_free_tx_ring_skbs(struct rtw_dev *rtwdev, + struct rtw_pci_tx_ring *tx_ring) + { +@@ -267,11 +261,6 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, + int i, allocated; + int ret = 0; + +- if (len > TRX_BD_IDX_MASK) { +- rtw_err(rtwdev, "len %d exceeds maximum RX entries\n", len); +- return -EINVAL; +- } +- + head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); + if (!head) { + rtw_err(rtwdev, "failed to allocate rx ring\n"); +@@ -327,7 +316,7 @@ static int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev) + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *tx_ring; + struct rtw_pci_rx_ring *rx_ring; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0; + int tx_desc_size, rx_desc_size; + u32 len; +@@ -488,13 +477,14 @@ static void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev) + } + + static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, +- struct rtw_pci *rtwpci) ++ struct rtw_pci *rtwpci, bool exclude_rx) + { + unsigned long flags; ++ u32 imr0_unmask = exclude_rx ? IMR_ROK : 0; + + spin_lock_irqsave(&rtwpci->hwirq_lock, flags); + +- rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0]); ++ rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0] & ~imr0_unmask); + rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); + if (rtw_chip_wcpu_11ac(rtwdev)) + rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); +@@ -546,7 +536,7 @@ static int rtw_pci_setup(struct rtw_dev *rtwdev) + static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) + { + struct rtw_pci_tx_ring *tx_ring; +- u8 queue; ++ enum rtw_tx_queue_type queue; + + rtw_pci_reset_trx_ring(rtwdev); + for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) { +@@ -555,12 +545,36 @@ static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) + } + } + ++static void rtw_pci_napi_start(struct rtw_dev *rtwdev) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ ++ if (test_and_set_bit(RTW_PCI_FLAG_NAPI_RUNNING, rtwpci->flags)) ++ return; ++ ++ napi_enable(&rtwpci->napi); ++} ++ ++static void rtw_pci_napi_stop(struct rtw_dev *rtwdev) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ ++ if (!test_and_clear_bit(RTW_PCI_FLAG_NAPI_RUNNING, rtwpci->flags)) ++ return; ++ ++ napi_synchronize(&rtwpci->napi); ++ napi_disable(&rtwpci->napi); ++} ++ + static int rtw_pci_start(struct rtw_dev *rtwdev) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + ++ rtw_pci_napi_start(rtwdev); ++ + spin_lock_bh(&rtwpci->irq_lock); +- rtw_pci_enable_interrupt(rtwdev, rtwpci); ++ rtwpci->running = true; ++ rtw_pci_enable_interrupt(rtwdev, rtwpci, false); + spin_unlock_bh(&rtwpci->irq_lock); + + return 0; +@@ -569,9 +583,17 @@ static int rtw_pci_start(struct rtw_dev *rtwdev) + static void rtw_pci_stop(struct rtw_dev *rtwdev) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ struct pci_dev *pdev = rtwpci->pdev; + + spin_lock_bh(&rtwpci->irq_lock); ++ rtwpci->running = false; + rtw_pci_disable_interrupt(rtwdev, rtwpci); ++ spin_unlock_bh(&rtwpci->irq_lock); ++ ++ synchronize_irq(pdev->irq); ++ rtw_pci_napi_stop(rtwdev); ++ ++ spin_lock_bh(&rtwpci->irq_lock); + rtw_pci_dma_release(rtwdev, rtwpci); + spin_unlock_bh(&rtwpci->irq_lock); + } +@@ -580,8 +602,11 @@ static void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *tx_ring; ++ enum rtw_tx_queue_type queue; + bool tx_empty = true; +- u8 queue; ++ ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) ++ goto enter_deep_ps; + + lockdep_assert_held(&rtwpci->irq_lock); + +@@ -608,7 +633,7 @@ static void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev) + "TX path not empty, cannot enter deep power save state\n"); + return; + } +- ++enter_deep_ps: + set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags); + rtw_power_mode_change(rtwdev, true); + } +@@ -638,32 +663,6 @@ static void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter) + spin_unlock_bh(&rtwpci->irq_lock); + } + +-static u8 ac_to_hwq[] = { +- [IEEE80211_AC_VO] = RTW_TX_QUEUE_VO, +- [IEEE80211_AC_VI] = RTW_TX_QUEUE_VI, +- [IEEE80211_AC_BE] = RTW_TX_QUEUE_BE, +- [IEEE80211_AC_BK] = RTW_TX_QUEUE_BK, +-}; +- +-static u8 rtw_hw_queue_mapping(struct sk_buff *skb) +-{ +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +- __le16 fc = hdr->frame_control; +- u8 q_mapping = skb_get_queue_mapping(skb); +- u8 queue; +- +- if (unlikely(ieee80211_is_beacon(fc))) +- queue = RTW_TX_QUEUE_BCN; +- else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) +- queue = RTW_TX_QUEUE_MGMT; +- else if (WARN_ON_ONCE(q_mapping >= ARRAY_SIZE(ac_to_hwq))) +- queue = ac_to_hwq[IEEE80211_AC_BE]; +- else +- queue = ac_to_hwq[q_mapping]; +- +- return queue; +-} +- + static void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci, + struct rtw_pci_tx_ring *ring) + { +@@ -685,7 +684,7 @@ static void rtw_pci_dma_check(struct rtw_dev *rtwdev, + u32 idx) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_rx_buffer_desc *buf_desc; + u32 desc_sz = chip->rx_buf_desc_sz; + u16 total_pkt_size; +@@ -701,7 +700,75 @@ static void rtw_pci_dma_check(struct rtw_dev *rtwdev, + rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX; + } + +-static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue) ++static u32 __pci_get_hw_tx_ring_rp(struct rtw_dev *rtwdev, u8 pci_q) ++{ ++ u32 bd_idx_addr = rtw_pci_tx_queue_idx_addr[pci_q]; ++ u32 bd_idx = rtw_read16(rtwdev, bd_idx_addr + 2); ++ ++ return FIELD_GET(TRX_BD_IDX_MASK, bd_idx); ++} ++ ++static void __pci_flush_queue(struct rtw_dev *rtwdev, u8 pci_q, bool drop) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ struct rtw_pci_tx_ring *ring = &rtwpci->tx_rings[pci_q]; ++ u32 cur_rp; ++ u8 i; ++ ++ /* Because the time taked by the I/O in __pci_get_hw_tx_ring_rp is a ++ * bit dynamic, it's hard to define a reasonable fixed total timeout to ++ * use read_poll_timeout* helper. Instead, we can ensure a reasonable ++ * polling times, so we just use for loop with udelay here. ++ */ ++ for (i = 0; i < 30; i++) { ++ cur_rp = __pci_get_hw_tx_ring_rp(rtwdev, pci_q); ++ if (cur_rp == ring->r.wp) ++ return; ++ ++ udelay(1); ++ } ++ ++ if (!drop) ++ rtw_warn(rtwdev, "timed out to flush pci tx ring[%d]\n", pci_q); ++} ++ ++static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues, ++ bool drop) ++{ ++ u8 q; ++ ++ for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) { ++ /* Unnecessary to flush BCN, H2C and HI tx queues. */ ++ if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C || ++ q == RTW_TX_QUEUE_HI0) ++ continue; ++ ++ if (pci_queues & BIT(q)) ++ __pci_flush_queue(rtwdev, q, drop); ++ } ++} ++ ++static void rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) ++{ ++ u32 pci_queues = 0; ++ u8 i; ++ ++ /* If all of the hardware queues are requested to flush, ++ * flush all of the pci queues. ++ */ ++ if (queues == BIT(rtwdev->hw->queues) - 1) { ++ pci_queues = BIT(RTK_MAX_TX_QUEUE_NUM) - 1; ++ } else { ++ for (i = 0; i < rtwdev->hw->queues; i++) ++ if (queues & BIT(i)) ++ pci_queues |= BIT(rtw_tx_ac_to_hwq(i)); ++ } ++ ++ __rtw_pci_flush_queues(rtwdev, pci_queues, drop); ++} ++ ++static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, ++ enum rtw_tx_queue_type queue) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *ring; +@@ -711,7 +778,8 @@ static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue) + bd_idx = rtw_pci_tx_queue_idx_addr[queue]; + + spin_lock_bh(&rtwpci->irq_lock); +- rtw_pci_deep_ps_leave(rtwdev); ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) ++ rtw_pci_deep_ps_leave(rtwdev); + rtw_write16(rtwdev, bd_idx, ring->r.wp & TRX_BD_IDX_MASK); + spin_unlock_bh(&rtwpci->irq_lock); + } +@@ -719,7 +787,7 @@ static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue) + static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; +- u8 queue; ++ enum rtw_tx_queue_type queue; + + for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) + if (test_and_clear_bit(queue, rtwpci->tx_queued)) +@@ -728,10 +796,11 @@ static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev) + + static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, +- struct sk_buff *skb, u8 queue) ++ struct sk_buff *skb, ++ enum rtw_tx_queue_type queue) + { + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_tx_ring *ring; + struct rtw_pci_tx_data *tx_data; + dma_addr_t dma; +@@ -846,9 +915,9 @@ static int rtw_pci_tx_write(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) + { ++ enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb); + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *ring; +- u8 queue = rtw_hw_queue_mapping(skb); + int ret; + + ret = rtw_pci_tx_write_data(rtwdev, pkt_info, skb, queue); +@@ -856,10 +925,12 @@ static int rtw_pci_tx_write(struct rtw_dev *rtwdev, + return ret; + + ring = &rtwpci->tx_rings[queue]; ++ spin_lock_bh(&rtwpci->irq_lock); + if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) { + ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb)); + ring->queue_stopped = true; + } ++ spin_unlock_bh(&rtwpci->irq_lock); + + return 0; + } +@@ -874,7 +945,7 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + struct sk_buff *skb; + u32 count; + u32 bd_idx_addr; +- u32 bd_idx, cur_rp; ++ u32 bd_idx, cur_rp, rp_idx; + u16 q_map; + + ring = &rtwpci->tx_rings[hw_queue]; +@@ -883,6 +954,7 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + bd_idx = rtw_read32(rtwdev, bd_idx_addr); + cur_rp = bd_idx >> 16; + cur_rp &= TRX_BD_IDX_MASK; ++ rp_idx = ring->r.rp; + if (cur_rp >= ring->r.rp) + count = cur_rp - ring->r.rp; + else +@@ -906,12 +978,15 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + } + + if (ring->queue_stopped && +- avail_desc(ring->r.wp, ring->r.rp, ring->r.len) > 4) { ++ avail_desc(ring->r.wp, rp_idx, ring->r.len) > 4) { + q_map = skb_get_queue_mapping(skb); + ieee80211_wake_queue(hw, q_map); + ring->queue_stopped = false; + } + ++ if (++rp_idx >= ring->r.len) ++ rp_idx = 0; ++ + skb_pull(skb, rtwdev->chip->tx_pkt_desc_sz); + + info = IEEE80211_SKB_CB(skb); +@@ -935,16 +1010,43 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + ring->r.rp = cur_rp; + } + +-static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, +- u8 hw_queue) ++static void rtw_pci_rx_isr(struct rtw_dev *rtwdev) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ struct napi_struct *napi = &rtwpci->napi; ++ ++ napi_schedule(napi); ++} ++ ++static int rtw_pci_get_hw_rx_ring_nr(struct rtw_dev *rtwdev, ++ struct rtw_pci *rtwpci) + { +- struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_rx_ring *ring; ++ int count = 0; ++ u32 tmp, cur_wp; ++ ++ ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; ++ tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ); ++ cur_wp = u32_get_bits(tmp, TRX_BD_HW_IDX_MASK); ++ if (cur_wp >= ring->r.wp) ++ count = cur_wp - ring->r.wp; ++ else ++ count = ring->r.len - (ring->r.wp - cur_wp); ++ ++ return count; ++} ++ ++static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, ++ u8 hw_queue, u32 limit) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct napi_struct *napi = &rtwpci->napi; ++ struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; + struct rtw_rx_pkt_stat pkt_stat; + struct ieee80211_rx_status rx_status; + struct sk_buff *skb, *new; +- u32 cur_wp, cur_rp, tmp; +- u32 count; ++ u32 cur_rp = ring->r.rp; ++ u32 count, rx_done = 0; + u32 pkt_offset; + u32 pkt_desc_sz = chip->rx_pkt_desc_sz; + u32 buf_desc_sz = chip->rx_buf_desc_sz; +@@ -952,17 +1054,9 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + u8 *rx_desc; + dma_addr_t dma; + +- ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; +- +- tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ); +- cur_wp = tmp >> 16; +- cur_wp &= TRX_BD_IDX_MASK; +- if (cur_wp >= ring->r.wp) +- count = cur_wp - ring->r.wp; +- else +- count = ring->r.len - (ring->r.wp - cur_wp); ++ count = rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci); ++ count = min(count, limit); + +- cur_rp = ring->r.rp; + while (count--) { + rtw_pci_dma_check(rtwdev, ring, cur_rp); + skb = ring->buf[cur_rp]; +@@ -995,7 +1089,8 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + + rtw_rx_stats(rtwdev, pkt_stat.vif, new); + memcpy(new->cb, &rx_status, sizeof(rx_status)); +- ieee80211_rx_irqsafe(rtwdev->hw, new); ++ ieee80211_rx_napi(rtwdev->hw, NULL, new, napi); ++ rx_done++; + } + + next_rp: +@@ -1009,8 +1104,13 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + } + + ring->r.rp = cur_rp; +- ring->r.wp = cur_wp; ++ /* 'rp', the last position we have read, is seen as previous posistion ++ * of 'wp' that is used to calculate 'count' next time. ++ */ ++ ring->r.wp = cur_rp; + rtw_write16(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ, ring->r.rp); ++ ++ return rx_done; + } + + static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, +@@ -1060,6 +1160,7 @@ static irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) + struct rtw_dev *rtwdev = dev; + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + u32 irq_status[4]; ++ bool rx = false; + + spin_lock_bh(&rtwpci->irq_lock); + rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status); +@@ -1078,13 +1179,16 @@ static irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_VI); + if (irq_status[3] & IMR_H2CDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_H2C); +- if (irq_status[0] & IMR_ROK) +- rtw_pci_rx_isr(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU); ++ if (irq_status[0] & IMR_ROK) { ++ rtw_pci_rx_isr(rtwdev); ++ rx = true; ++ } + if (unlikely(irq_status[0] & IMR_C2HCMD)) + rtw_fw_c2h_cmd_isr(rtwdev); + + /* all of the jobs for this interrupt have been done */ +- rtw_pci_enable_interrupt(rtwdev, rtwpci); ++ if (rtwpci->running) ++ rtw_pci_enable_interrupt(rtwdev, rtwpci, rx); + spin_unlock_bh(&rtwpci->irq_lock); + + return IRQ_HANDLED; +@@ -1222,6 +1326,25 @@ static void rtw_pci_clkreq_set(struct rtw_dev *rtwdev, bool enable) + rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value); + } + ++static void rtw_pci_clkreq_pad_low(struct rtw_dev *rtwdev, bool enable) ++{ ++ u8 value; ++ int ret; ++ ++ ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value); ++ if (ret) { ++ rtw_err(rtwdev, "failed to read CLKREQ_L1, ret=%d", ret); ++ return; ++ } ++ ++ if (enable) ++ value &= ~BIT_CLKREQ_N_PAD; ++ else ++ value |= BIT_CLKREQ_N_PAD; ++ ++ rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value); ++} ++ + static void rtw_pci_aspm_set(struct rtw_dev *rtwdev, bool enable) + { + u8 value; +@@ -1258,13 +1381,17 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter) + * throughput. This is probably because the ASPM behavior slightly + * varies from different SOC. + */ +- if (rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1) ++ if (!(rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1)) ++ return; ++ ++ if ((enter && atomic_dec_if_positive(&rtwpci->link_usage) == 0) || ++ (!enter && atomic_inc_return(&rtwpci->link_usage) == 1)) + rtw_pci_aspm_set(rtwdev, enter); + } + + static void rtw_pci_link_cfg(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct pci_dev *pdev = rtwpci->pdev; + u16 link_ctrl; +@@ -1306,7 +1433,7 @@ static void rtw_pci_link_cfg(struct rtw_dev *rtwdev) + + static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + switch (chip->id) { + case RTW_CHIP_TYPE_8822C: +@@ -1321,12 +1448,15 @@ static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) + + static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct pci_dev *pdev = rtwpci->pdev; + const struct rtw_intf_phy_para *para; + u16 cut; + u16 value; + u16 offset; + int i; ++ int ret; + + cut = BIT(0) << rtwdev->hal.cut_version; + +@@ -1359,15 +1489,38 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) + } + + rtw_pci_link_cfg(rtwdev); ++ ++ /* Disable 8821ce completion timeout by default */ ++ if (chip->id == RTW_CHIP_TYPE_8821C) { ++ ret = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2, ++ PCI_EXP_DEVCTL2_COMP_TMOUT_DIS); ++ if (ret) ++ rtw_err(rtwdev, "failed to set PCI cap, ret = %d\n", ++ ret); ++ } + } + + static int __maybe_unused rtw_pci_suspend(struct device *dev) + { ++ struct ieee80211_hw *hw = dev_get_drvdata(dev); ++ struct rtw_dev *rtwdev = hw->priv; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ ++ if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6) ++ rtw_pci_clkreq_pad_low(rtwdev, true); + return 0; + } + + static int __maybe_unused rtw_pci_resume(struct device *dev) + { ++ struct ieee80211_hw *hw = dev_get_drvdata(dev); ++ struct rtw_dev *rtwdev = hw->priv; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ ++ if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6) ++ rtw_pci_clkreq_pad_low(rtwdev, false); + return 0; + } + +@@ -1393,7 +1546,6 @@ static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev) + + static void rtw_pci_declaim(struct rtw_dev *rtwdev, struct pci_dev *pdev) + { +- pci_clear_master(pdev); + pci_disable_device(pdev); + } + +@@ -1436,6 +1588,7 @@ static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev) + static struct rtw_hci_ops rtw_pci_ops = { + .tx_write = rtw_pci_tx_write, + .tx_kick_off = rtw_pci_tx_kick_off, ++ .flush_queues = rtw_pci_flush_queues, + .setup = rtw_pci_setup, + .start = rtw_pci_start, + .stop = rtw_pci_stop, +@@ -1485,11 +1638,73 @@ static void rtw_pci_free_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev) + pci_free_irq_vectors(pdev); + } + ++static int rtw_pci_napi_poll(struct napi_struct *napi, int budget) ++{ ++ struct rtw_pci *rtwpci = container_of(napi, struct rtw_pci, napi); ++ struct rtw_dev *rtwdev = container_of((void *)rtwpci, struct rtw_dev, ++ priv); ++ int work_done = 0; ++ ++ if (rtwpci->rx_no_aspm) ++ rtw_pci_link_ps(rtwdev, false); ++ ++ while (work_done < budget) { ++ u32 work_done_once; ++ ++ work_done_once = rtw_pci_rx_napi(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU, ++ budget - work_done); ++ if (work_done_once == 0) ++ break; ++ work_done += work_done_once; ++ } ++ if (work_done < budget) { ++ napi_complete_done(napi, work_done); ++ spin_lock_bh(&rtwpci->irq_lock); ++ if (rtwpci->running) ++ rtw_pci_enable_interrupt(rtwdev, rtwpci, false); ++ spin_unlock_bh(&rtwpci->irq_lock); ++ /* When ISR happens during polling and before napi_complete ++ * while no further data is received. Data on the dma_ring will ++ * not be processed immediately. Check whether dma ring is ++ * empty and perform napi_schedule accordingly. ++ */ ++ if (rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci)) ++ napi_schedule(napi); ++ } ++ if (rtwpci->rx_no_aspm) ++ rtw_pci_link_ps(rtwdev, true); ++ ++ return work_done; ++} ++ ++static void rtw_pci_napi_init(struct rtw_dev *rtwdev) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ ++ init_dummy_netdev(&rtwpci->netdev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll); ++#else ++ netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll, ++ NAPI_POLL_WEIGHT); ++#endif ++} ++ ++static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev) ++{ ++ struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; ++ ++ rtw_pci_napi_stop(rtwdev); ++ netif_napi_del(&rtwpci->napi); ++} ++ + int rtw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) + { ++ struct pci_dev *bridge = pci_upstream_bridge(pdev); + struct ieee80211_hw *hw; + struct rtw_dev *rtwdev; ++ struct rtw_pci *rtwpci; + int drv_data_size; + int ret; + +@@ -1507,6 +1722,9 @@ int rtw_pci_probe(struct pci_dev *pdev, + rtwdev->hci.ops = &rtw_pci_ops; + rtwdev->hci.type = RTW_HCI_TYPE_PCIE; + ++ rtwpci = (struct rtw_pci *)rtwdev->priv; ++ atomic_set(&rtwpci->link_usage, 1); ++ + ret = rtw_core_init(rtwdev); + if (ret) + goto err_release_hw; +@@ -1527,12 +1745,18 @@ int rtw_pci_probe(struct pci_dev *pdev, + goto err_pci_declaim; + } + ++ rtw_pci_napi_init(rtwdev); ++ + ret = rtw_chip_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip information\n"); + goto err_destroy_pci; + } + ++ /* Disable PCIe ASPM L1 while doing NAPI poll for 8821CE */ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821C && bridge->vendor == PCI_VENDOR_ID_INTEL) ++ rtwpci->rx_no_aspm = true; ++ + rtw_pci_phy_cfg(rtwdev); + + ret = rtw_register_hw(rtwdev, hw); +@@ -1550,6 +1774,7 @@ int rtw_pci_probe(struct pci_dev *pdev, + return 0; + + err_destroy_pci: ++ rtw_pci_napi_deinit(rtwdev); + rtw_pci_destroy(rtwdev, pdev); + + err_pci_declaim: +@@ -1579,6 +1804,7 @@ void rtw_pci_remove(struct pci_dev *pdev) + + rtw_unregister_hw(rtwdev, hw); + rtw_pci_disable_interrupt(rtwdev, rtwpci); ++ rtw_pci_napi_deinit(rtwdev); + rtw_pci_destroy(rtwdev, pdev); + rtw_pci_declaim(rtwdev, pdev); + rtw_pci_free_irq(rtwdev, pdev); +@@ -1591,7 +1817,7 @@ void rtw_pci_shutdown(struct pci_dev *pdev) + { + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw_dev *rtwdev; +- struct rtw_chip_info *chip; ++ const struct rtw_chip_info *chip; + + if (!hw) + return; +diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h +index ca17aa9cf7dc..0c37efd8c66f 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.h ++++ b/drivers/net/wireless/realtek/rtw88/pci.h +@@ -5,6 +5,8 @@ + #ifndef __RTK_PCI_H_ + #define __RTK_PCI_H_ + ++#include "main.h" ++ + #define RTK_DEFAULT_TX_DESC_NUM 128 + #define RTK_BEQ_TX_DESC_NUM 256 + +@@ -35,6 +37,7 @@ + #define RTK_PCIE_LINK_CFG 0x0719 + #define BIT_CLKREQ_SW_EN BIT(4) + #define BIT_L1_SW_EN BIT(3) ++#define BIT_CLKREQ_N_PAD BIT(0) + #define RTK_PCIE_CLKDLY_CTRL 0x0725 + + #define BIT_PCI_BCNQ_FLAG BIT(4) +@@ -49,6 +52,7 @@ + #define RTK_PCI_RXBD_DESA_MPDUQ 0x338 + + #define TRX_BD_IDX_MASK GENMASK(11, 0) ++#define TRX_BD_HW_IDX_MASK GENMASK(27, 16) + + /* BCNQ is specialized for rsvd page, does not need to specify a number */ + #define RTK_PCI_TXBD_NUM_H2CQ 0x1328 +@@ -140,6 +144,12 @@ + /* IMR 3 */ + #define IMR_H2CDOK BIT(16) + ++enum rtw_pci_flags { ++ RTW_PCI_FLAG_NAPI_RUNNING, ++ ++ NUM_OF_RTW_PCI_FLAGS, ++}; ++ + /* one element is reserved to know if the ring is closed */ + static inline int avail_desc(u32 wp, u32 rp, u32 len) + { +@@ -198,20 +208,34 @@ struct rtw_pci { + + /* Used for PCI interrupt. */ + spinlock_t hwirq_lock; +- /* Used for PCI TX queueing. */ ++ /* Used for PCI TX ring/queueing, and enable INT. */ + spinlock_t irq_lock; + u32 irq_mask[4]; + bool irq_enabled; ++ bool running; ++ ++ /* napi structure */ ++ struct net_device netdev; ++ struct napi_struct napi; + + u16 rx_tag; + DECLARE_BITMAP(tx_queued, RTK_MAX_TX_QUEUE_NUM); + struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM]; + struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM]; + u16 link_ctrl; ++ atomic_t link_usage; ++ bool rx_no_aspm; ++ DECLARE_BITMAP(flags, NUM_OF_RTW_PCI_FLAGS); + + void __iomem *mmap; + }; + ++extern const struct dev_pm_ops rtw_pm_ops; ++ ++int rtw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); ++void rtw_pci_remove(struct pci_dev *pdev); ++void rtw_pci_shutdown(struct pci_dev *pdev); ++ + static inline u32 max_num_of_tx_queue(u8 queue) + { + u32 max_num; +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index af8b703d11d4..28e615cde174 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -9,6 +9,10 @@ + #include "fw.h" + #include "phy.h" + #include "debug.h" ++#include "regd.h" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++#include "sar.h" ++#endif + + struct phy_cfg_pair { + u32 addr; +@@ -119,9 +123,85 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) + dm_info->cck_fa_avg = CCK_FA_AVG_RESET; + } + ++void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) ++{ ++ struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; ++ ++ rtw_write32_mask(rtwdev, ++ edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, ++ edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask, ++ l2h + edcca_th[EDCCA_TH_L2H_IDX].offset); ++ rtw_write32_mask(rtwdev, ++ edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr, ++ edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask, ++ h2l + edcca_th[EDCCA_TH_H2L_IDX].offset); ++} ++EXPORT_SYMBOL(rtw_phy_set_edcca_th); ++ ++void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ /* turn off in debugfs for debug usage */ ++ if (!rtw_edcca_enabled) { ++ dm_info->edcca_mode = RTW_EDCCA_NORMAL; ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "EDCCA disabled, cannot be set\n"); ++ return; ++ } ++ ++ switch (rtwdev->regd.dfs_region) { ++ case NL80211_DFS_ETSI: ++ dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; ++ dm_info->l2h_th_ini = chip->l2h_th_ini_ad; ++ break; ++ case NL80211_DFS_JP: ++ dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; ++ dm_info->l2h_th_ini = chip->l2h_th_ini_cs; ++ break; ++ default: ++ dm_info->edcca_mode = RTW_EDCCA_NORMAL; ++ break; ++ } ++} ++ ++static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ rtw_phy_adaptivity_set_mode(rtwdev); ++ if (chip->ops->adaptivity_init) ++ chip->ops->adaptivity_init(rtwdev); ++} ++ ++static void rtw_phy_adaptivity(struct rtw_dev *rtwdev) ++{ ++ if (rtwdev->chip->ops->adaptivity) ++ rtwdev->chip->ops->adaptivity(rtwdev); ++} ++ ++static void rtw_phy_cfo_init(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ if (chip->ops->cfo_init) ++ chip->ops->cfo_init(rtwdev); ++} ++ ++static void rtw_phy_tx_path_div_init(struct rtw_dev *rtwdev) ++{ ++ struct rtw_path_div *path_div = &rtwdev->dm_path_div; ++ ++ path_div->current_tx_path = rtwdev->chip->default_1ss_tx_path; ++ path_div->path_a_cnt = 0; ++ path_div->path_a_sum = 0; ++ path_div->path_b_cnt = 0; ++ path_div->path_b_sum = 0; ++} ++ + void rtw_phy_init(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 addr, mask; + +@@ -140,12 +220,15 @@ void rtw_phy_init(struct rtw_dev *rtwdev) + rtw_phy_cck_pd_init(rtwdev); + + dm_info->iqk.done = false; ++ rtw_phy_adaptivity_init(rtwdev); ++ rtw_phy_cfo_init(rtwdev); ++ rtw_phy_tx_path_div_init(rtwdev); + } + EXPORT_SYMBOL(rtw_phy_init); + + void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + u32 addr, mask; + u8 path; +@@ -164,7 +247,7 @@ void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) + + static void rtw_phy_stat_false_alarm(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->false_alarm_statistics(rtwdev); + } +@@ -219,7 +302,7 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev) + + data.rtwdev = rtwdev; + data.min_rssi = U8_MAX; +- rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data); ++ rtw_iterate_stas(rtwdev, rtw_phy_stat_rssi_iter, &data); + + dm_info->pre_min_rssi = dm_info->min_rssi; + dm_info->min_rssi = data.min_rssi; +@@ -316,7 +399,8 @@ rtw_phy_dig_check_damping(struct rtw_dm_info *dm_info) + return damping; + } + +-static void rtw_phy_dig_get_boundary(struct rtw_dm_info *dm_info, ++static void rtw_phy_dig_get_boundary(struct rtw_dev *rtwdev, ++ struct rtw_dm_info *dm_info, + u8 *upper, u8 *lower, bool linked) + { + u8 dig_max, dig_min, dig_mid; +@@ -325,8 +409,7 @@ static void rtw_phy_dig_get_boundary(struct rtw_dm_info *dm_info, + if (linked) { + dig_max = DIG_PERF_MAX; + dig_mid = DIG_PERF_MID; +- /* 22B=0x1c, 22C=0x20 */ +- dig_min = 0x1c; ++ dig_min = rtwdev->chip->dig_min; + min_rssi = max_t(u8, dm_info->min_rssi, dig_min); + } else { + dig_max = DIG_CVRG_MAX; +@@ -437,7 +520,8 @@ static void rtw_phy_dig(struct rtw_dev *rtwdev) + * the peers connected with us, meanwhile make sure the igi value does + * not beyond the hardware limitation + */ +- rtw_phy_dig_get_boundary(dm_info, &upper_bound, &lower_bound, linked); ++ rtw_phy_dig_get_boundary(rtwdev, dm_info, &upper_bound, &lower_bound, ++ linked); + cur_igi = clamp_t(u8, cur_igi, lower_bound, upper_bound); + + /* record current igi value and false alarm statistics for further +@@ -454,7 +538,7 @@ static void rtw_phy_ra_info_update_iter(void *data, struct ieee80211_sta *sta) + struct rtw_dev *rtwdev = data; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + +- rtw_update_sta_info(rtwdev, si); ++ rtw_update_sta_info(rtwdev, si, false); + } + + static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) +@@ -462,17 +546,127 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) + if (rtwdev->watch_dog_cnt & 0x3) + return; + +- rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); ++ rtw_iterate_stas(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); ++} ++ ++static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) ++{ ++ u8 rate_order; ++ ++ rate_order = rate_idx; ++ ++ if (rate_idx >= DESC_RATEVHT4SS_MCS0) ++ rate_order -= DESC_RATEVHT4SS_MCS0; ++ else if (rate_idx >= DESC_RATEVHT3SS_MCS0) ++ rate_order -= DESC_RATEVHT3SS_MCS0; ++ else if (rate_idx >= DESC_RATEVHT2SS_MCS0) ++ rate_order -= DESC_RATEVHT2SS_MCS0; ++ else if (rate_idx >= DESC_RATEVHT1SS_MCS0) ++ rate_order -= DESC_RATEVHT1SS_MCS0; ++ else if (rate_idx >= DESC_RATEMCS24) ++ rate_order -= DESC_RATEMCS24; ++ else if (rate_idx >= DESC_RATEMCS16) ++ rate_order -= DESC_RATEMCS16; ++ else if (rate_idx >= DESC_RATEMCS8) ++ rate_order -= DESC_RATEMCS8; ++ else if (rate_idx >= DESC_RATEMCS0) ++ rate_order -= DESC_RATEMCS0; ++ else if (rate_idx >= DESC_RATE6M) ++ rate_order -= DESC_RATE6M; ++ else ++ rate_order -= DESC_RATE1M; ++ ++ if (rate_idx >= DESC_RATEMCS0 || rate_order == 0) ++ rate_order++; ++ ++ return GENMASK(rate_order + RRSR_RATE_ORDER_CCK_LEN - 1, 0); ++} ++ ++static void rtw_phy_rrsr_mask_min_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw_dev *rtwdev = (struct rtw_dev *)data; ++ struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u32 mask = 0; ++ ++ mask = rtw_phy_get_rrsr_mask(rtwdev, si->ra_report.desc_rate); ++ if (mask < dm_info->rrsr_mask_min) ++ dm_info->rrsr_mask_min = mask; ++} ++ ++static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ ++ dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX; ++ rtw_iterate_stas(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); ++ rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min); + } + + static void rtw_phy_dpk_track(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + + if (chip->ops->dpk_track) + chip->ops->dpk_track(rtwdev); + } + ++struct rtw_rx_addr_match_data { ++ struct rtw_dev *rtwdev; ++ struct ieee80211_hdr *hdr; ++ struct rtw_rx_pkt_stat *pkt_stat; ++ u8 *bssid; ++}; ++ ++static void rtw_phy_parsing_cfo_iter(void *data, u8 *mac, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw_rx_addr_match_data *iter_data = data; ++ struct rtw_dev *rtwdev = iter_data->rtwdev; ++ struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ u8 *bssid = iter_data->bssid; ++ u8 i; ++ ++ if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) ++ return; ++ ++ for (i = 0; i < rtwdev->hal.rf_path_num; i++) { ++ cfo->cfo_tail[i] += pkt_stat->cfo_tail[i]; ++ cfo->cfo_cnt[i]++; ++ } ++ ++ cfo->packet_count++; ++} ++ ++void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, ++ struct rtw_rx_pkt_stat *pkt_stat) ++{ ++ struct ieee80211_hdr *hdr = pkt_stat->hdr; ++ struct rtw_rx_addr_match_data data = {}; ++ ++ if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || ++ ieee80211_is_ctl(hdr->frame_control)) ++ return; ++ ++ data.rtwdev = rtwdev; ++ data.hdr = hdr; ++ data.pkt_stat = pkt_stat; ++ data.bssid = get_hdr_bssid(hdr); ++ ++ rtw_iterate_vifs_atomic(rtwdev, rtw_phy_parsing_cfo_iter, &data); ++} ++EXPORT_SYMBOL(rtw_phy_parsing_cfo); ++ ++static void rtw_phy_cfo_track(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ if (chip->ops->cfo_track) ++ chip->ops->cfo_track(rtwdev); ++} ++ + #define CCK_PD_FA_LV1_MIN 1000 + #define CCK_PD_FA_LV0_MAX 500 + +@@ -528,8 +722,8 @@ static u8 rtw_phy_cck_pd_lv(struct rtw_dev *rtwdev) + + static void rtw_phy_cck_pd(struct rtw_dev *rtwdev) + { ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- struct rtw_chip_info *chip = rtwdev->chip; + u32 cck_fa = dm_info->cck_fa_cnt; + u8 level; + +@@ -541,6 +735,12 @@ static void rtw_phy_cck_pd(struct rtw_dev *rtwdev) + else + dm_info->cck_fa_avg = (dm_info->cck_fa_avg * 3 + cck_fa) >> 2; + ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "IGI=0x%x, rssi_min=%d, cck_fa=%d\n", ++ dm_info->igi_history[0], dm_info->min_rssi, ++ dm_info->fa_history[0]); ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "cck_fa_avg=%d, cck_pd_default=%d\n", ++ dm_info->cck_fa_avg, dm_info->cck_pd_default); ++ + level = rtw_phy_cck_pd_lv(rtwdev); + + if (level >= CCK_PD_LV_MAX) +@@ -555,15 +755,29 @@ static void rtw_phy_pwr_track(struct rtw_dev *rtwdev) + rtwdev->chip->ops->pwr_track(rtwdev); + } + ++static void rtw_phy_ra_track(struct rtw_dev *rtwdev) ++{ ++ rtw_fw_update_wl_phy_info(rtwdev); ++ rtw_phy_ra_info_update(rtwdev); ++ rtw_phy_rrsr_update(rtwdev); ++} ++ + void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev) + { + /* for further calculation */ + rtw_phy_statistics(rtwdev); + rtw_phy_dig(rtwdev); + rtw_phy_cck_pd(rtwdev); +- rtw_phy_ra_info_update(rtwdev); ++ rtw_phy_ra_track(rtwdev); ++ rtw_phy_tx_path_diversity(rtwdev); ++ rtw_phy_cfo_track(rtwdev); + rtw_phy_dpk_track(rtwdev); + rtw_phy_pwr_track(rtwdev); ++ ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_ADAPTIVITY)) ++ rtw_fw_adaptivity(rtwdev); ++ else ++ rtw_phy_adaptivity(rtwdev); + } + + #define FRAC_BITS 3 +@@ -604,23 +818,18 @@ static u8 rtw_phy_linear_2_db(u64 linear) + u8 j; + u32 dB; + +- if (linear >= db_invert_table[11][7]) +- return 96; /* maximum 96 dB */ +- + for (i = 0; i < 12; i++) { +- if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][7]) +- break; +- else if (i > 2 && linear <= db_invert_table[i][7]) +- break; ++ for (j = 0; j < 8; j++) { ++ if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) ++ goto cnt; ++ else if (i > 2 && linear <= db_invert_table[i][j]) ++ goto cnt; ++ } + } + +- for (j = 0; j < 8; j++) { +- if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) +- break; +- else if (i > 2 && linear <= db_invert_table[i][j]) +- break; +- } ++ return 96; /* maximum 96 dB */ + ++cnt: + if (j == 0 && i == 0) + goto end; + +@@ -688,7 +897,7 @@ u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask) + { + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const u32 *base_addr = chip->rf_base_addr; + u32 val, direct_addr; + +@@ -711,7 +920,7 @@ u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask) + { + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_rf_sipi_addr *rf_sipi_addr; + const struct rtw_rf_sipi_addr *rf_sipi_addr_a; + u32 val32; +@@ -760,8 +969,8 @@ bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) + { + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; +- u32 *sipi_addr = chip->rf_sipi_addr; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ const u32 *sipi_addr = chip->rf_sipi_addr; + u32 data_and_addr; + u32 old_data = 0; + u32 shift; +@@ -800,7 +1009,7 @@ bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) + { + struct rtw_hal *hal = &rtwdev->hal; +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const u32 *base_addr = chip->rf_base_addr; + u32 direct_addr; + +@@ -1417,17 +1626,70 @@ static void rtw_xref_txpwr_lmt(struct rtw_dev *rtwdev) + rtw_xref_txpwr_lmt_by_bw(rtwdev, regd); + } + ++static void ++__cfg_txpwr_lmt_by_alt(struct rtw_hal *hal, u8 regd, u8 regd_alt, u8 bw, u8 rs) ++{ ++ u8 ch; ++ ++ for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) ++ hal->tx_pwr_limit_2g[regd][bw][rs][ch] = ++ hal->tx_pwr_limit_2g[regd_alt][bw][rs][ch]; ++ ++ for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) ++ hal->tx_pwr_limit_5g[regd][bw][rs][ch] = ++ hal->tx_pwr_limit_5g[regd_alt][bw][rs][ch]; ++} ++ ++static void ++rtw_cfg_txpwr_lmt_by_alt(struct rtw_dev *rtwdev, u8 regd, u8 regd_alt) ++{ ++ u8 bw, rs; ++ ++ for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) ++ for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) ++ __cfg_txpwr_lmt_by_alt(&rtwdev->hal, regd, regd_alt, ++ bw, rs); ++} ++ + void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, + const struct rtw_table *tbl) + { + const struct rtw_txpwr_lmt_cfg_pair *p = tbl->data; + const struct rtw_txpwr_lmt_cfg_pair *end = p + tbl->size; ++ u32 regd_cfg_flag = 0; ++ u8 regd_alt; ++ u8 i; + + for (; p < end; p++) { ++ regd_cfg_flag |= BIT(p->regd); + rtw_phy_set_tx_power_limit(rtwdev, p->regd, p->band, + p->bw, p->rs, p->ch, p->txpwr_lmt); + } + ++ for (i = 0; i < RTW_REGD_MAX; i++) { ++ if (i == RTW_REGD_WW) ++ continue; ++ ++ if (regd_cfg_flag & BIT(i)) ++ continue; ++ ++ rtw_dbg(rtwdev, RTW_DBG_REGD, ++ "txpwr regd %d does not be configured\n", i); ++ ++ if (rtw_regd_has_alt(i, ®d_alt) && ++ regd_cfg_flag & BIT(regd_alt)) { ++ rtw_dbg(rtwdev, RTW_DBG_REGD, ++ "cfg txpwr regd %d by regd %d as alternative\n", ++ i, regd_alt); ++ ++ rtw_cfg_txpwr_lmt_by_alt(rtwdev, i, regd_alt); ++ continue; ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_REGD, "cfg txpwr regd %d by WW\n", i); ++ rtw_cfg_txpwr_lmt_by_alt(rtwdev, i, RTW_REGD_WW); ++ } ++ + rtw_xref_txpwr_lmt(rtwdev); + } + EXPORT_SYMBOL(rtw_parse_tbl_txpwr_lmt); +@@ -1482,7 +1744,7 @@ EXPORT_SYMBOL(rtw_phy_cfg_rf); + + static void rtw_load_rfk_table(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info; + + if (!chip->rfk_init_tbl) +@@ -1501,12 +1763,15 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev) + + void rtw_phy_load_tables(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 rf_path; + + rtw_load_table(rtwdev, chip->mac_tbl); + rtw_load_table(rtwdev, chip->bb_tbl); + rtw_load_table(rtwdev, chip->agc_tbl); ++ if (rfe_def->agc_btg_tbl) ++ rtw_load_table(rtwdev, rfe_def->agc_btg_tbl); + rtw_load_rfk_table(rtwdev); + + for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) { +@@ -1610,7 +1875,7 @@ static u8 rtw_get_channel_group(u8 channel, u8 rate) + + static s8 rtw_phy_get_dis_dpd_by_rate_diff(struct rtw_dev *rtwdev, u16 rate) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + s8 dpd_diff = 0; + + if (!chip->en_dis_dpd) +@@ -1644,7 +1909,7 @@ static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev, + enum rtw_bandwidth bandwidth, + u8 rate, u8 group) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 tx_power; + bool mcs_rate; + bool above_2ss; +@@ -1691,7 +1956,7 @@ static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev, + enum rtw_bandwidth bandwidth, + u8 rate, u8 group) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + u8 tx_power; + u8 upper, lower; + bool mcs_rate; +@@ -1740,6 +2005,25 @@ static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev, + return tx_power; + } + ++/* return RTW_RATE_SECTION_MAX to indicate rate is invalid */ ++static u8 rtw_phy_rate_to_rate_section(u8 rate) ++{ ++ if (rate >= DESC_RATE1M && rate <= DESC_RATE11M) ++ return RTW_RATE_SECTION_CCK; ++ else if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) ++ return RTW_RATE_SECTION_OFDM; ++ else if (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS7) ++ return RTW_RATE_SECTION_HT_1S; ++ else if (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ++ return RTW_RATE_SECTION_HT_2S; ++ else if (rate >= DESC_RATEVHT1SS_MCS0 && rate <= DESC_RATEVHT1SS_MCS9) ++ return RTW_RATE_SECTION_VHT_1S; ++ else if (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9) ++ return RTW_RATE_SECTION_VHT_2S; ++ else ++ return RTW_RATE_SECTION_MAX; ++} ++ + static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + enum rtw_bandwidth bw, u8 rf_path, + u8 rate, u8 channel, u8 regd) +@@ -1747,7 +2031,7 @@ static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + struct rtw_hal *hal = &rtwdev->hal; + u8 *cch_by_bw = hal->cch_by_bw; + s8 power_limit = (s8)rtwdev->chip->max_power_index; +- u8 rs; ++ u8 rs = rtw_phy_rate_to_rate_section(rate); + int ch_idx; + u8 cur_bw, cur_ch; + s8 cur_lmt; +@@ -1755,19 +2039,7 @@ static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + if (regd > RTW_REGD_WW) + return power_limit; + +- if (rate >= DESC_RATE1M && rate <= DESC_RATE11M) +- rs = RTW_RATE_SECTION_CCK; +- else if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) +- rs = RTW_RATE_SECTION_OFDM; +- else if (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS7) +- rs = RTW_RATE_SECTION_HT_1S; +- else if (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) +- rs = RTW_RATE_SECTION_HT_2S; +- else if (rate >= DESC_RATEVHT1SS_MCS0 && rate <= DESC_RATEVHT1SS_MCS9) +- rs = RTW_RATE_SECTION_VHT_1S; +- else if (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9) +- rs = RTW_RATE_SECTION_VHT_2S; +- else ++ if (rs == RTW_RATE_SECTION_MAX) + goto err; + + /* only 20M BW with cck and ofdm */ +@@ -1801,6 +2073,29 @@ static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + return (s8)rtwdev->chip->max_power_index; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++static s8 rtw_phy_get_tx_power_sar(struct rtw_dev *rtwdev, u8 sar_band, ++ u8 rf_path, u8 rate) ++{ ++ u8 rs = rtw_phy_rate_to_rate_section(rate); ++ struct rtw_sar_arg arg = { ++ .sar_band = sar_band, ++ .path = rf_path, ++ .rs = rs, ++ }; ++ ++ if (rs == RTW_RATE_SECTION_MAX) ++ goto err; ++ ++ return rtw_query_sar(rtwdev, &arg); ++ ++err: ++ WARN(1, "invalid arguments, sar_band=%d, path=%d, rate=%d\n", ++ sar_band, rf_path, rate); ++ return (s8)rtwdev->chip->max_power_index; ++} ++#endif ++ + void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, + u8 ch, u8 regd, struct rtw_power_params *pwr_param) + { +@@ -1812,6 +2107,9 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, + s8 *offset = &pwr_param->pwr_offset; + s8 *limit = &pwr_param->pwr_limit; + s8 *remnant = &pwr_param->pwr_remnant; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ s8 *sar = &pwr_param->pwr_sar; ++#endif + + pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; + group = rtw_get_channel_group(ch, rate); +@@ -1835,6 +2133,9 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, + rate, ch, regd); + *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : + dm_info->txagc_remnant_ofdm); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ *sar = rtw_phy_get_tx_power_sar(rtwdev, hal->sar_band, path, rate); ++#endif + } + + u8 +@@ -1849,7 +2150,9 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate, + channel, regd, &pwr_param); + + tx_power = pwr_param.pwr_base; +- offset = min_t(s8, pwr_param.pwr_offset, pwr_param.pwr_limit); ++ offset = min3(pwr_param.pwr_offset, ++ pwr_param.pwr_limit, ++ pwr_param.pwr_sar); + + if (rtwdev->chip->en_dis_dpd) + offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); +@@ -1867,7 +2170,7 @@ static void rtw_phy_set_tx_power_index_by_rs(struct rtw_dev *rtwdev, + u8 ch, u8 path, u8 rs) + { + struct rtw_hal *hal = &rtwdev->hal; +- u8 regd = rtwdev->regd.txpwr_regd; ++ u8 regd = rtw_regd_get(rtwdev); + u8 *rates; + u8 size; + u8 rate; +@@ -1912,7 +2215,7 @@ static void rtw_phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev, + + void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + u8 path; + +@@ -2181,3 +2484,71 @@ bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev) + return false; + } + EXPORT_SYMBOL(rtw_phy_pwrtrack_need_iqk); ++ ++static void rtw_phy_set_tx_path_by_reg(struct rtw_dev *rtwdev, ++ enum rtw_bb_path tx_path_sel_1ss) ++{ ++ struct rtw_path_div *path_div = &rtwdev->dm_path_div; ++ enum rtw_bb_path tx_path_sel_cck = tx_path_sel_1ss; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ if (tx_path_sel_1ss == path_div->current_tx_path) ++ return; ++ ++ path_div->current_tx_path = tx_path_sel_1ss; ++ rtw_dbg(rtwdev, RTW_DBG_PATH_DIV, "Switch TX path=%s\n", ++ tx_path_sel_1ss == BB_PATH_A ? "A" : "B"); ++ chip->ops->config_tx_path(rtwdev, rtwdev->hal.antenna_tx, ++ tx_path_sel_1ss, tx_path_sel_cck, false); ++} ++ ++static void rtw_phy_tx_path_div_select(struct rtw_dev *rtwdev) ++{ ++ struct rtw_path_div *path_div = &rtwdev->dm_path_div; ++ enum rtw_bb_path path = path_div->current_tx_path; ++ s32 rssi_a = 0, rssi_b = 0; ++ ++ if (path_div->path_a_cnt) ++ rssi_a = path_div->path_a_sum / path_div->path_a_cnt; ++ else ++ rssi_a = 0; ++ if (path_div->path_b_cnt) ++ rssi_b = path_div->path_b_sum / path_div->path_b_cnt; ++ else ++ rssi_b = 0; ++ ++ if (rssi_a != rssi_b) ++ path = (rssi_a > rssi_b) ? BB_PATH_A : BB_PATH_B; ++ ++ path_div->path_a_cnt = 0; ++ path_div->path_a_sum = 0; ++ path_div->path_b_cnt = 0; ++ path_div->path_b_sum = 0; ++ rtw_phy_set_tx_path_by_reg(rtwdev, path); ++} ++ ++static void rtw_phy_tx_path_diversity_2ss(struct rtw_dev *rtwdev) ++{ ++ if (rtwdev->hal.antenna_rx != BB_PATH_AB) { ++ rtw_dbg(rtwdev, RTW_DBG_PATH_DIV, ++ "[Return] tx_Path_en=%d, rx_Path_en=%d\n", ++ rtwdev->hal.antenna_tx, rtwdev->hal.antenna_rx); ++ return; ++ } ++ if (rtwdev->sta_cnt == 0) { ++ rtw_dbg(rtwdev, RTW_DBG_PATH_DIV, "No Link\n"); ++ return; ++ } ++ ++ rtw_phy_tx_path_div_select(rtwdev); ++} ++ ++void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ if (!chip->path_div_supported) ++ return; ++ ++ rtw_phy_tx_path_diversity_2ss(rtwdev); ++} +diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h +index 9623248c9466..ccfcbd3ced03 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.h ++++ b/drivers/net/wireless/realtek/rtw88/phy.h +@@ -59,6 +59,11 @@ bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev); + bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev); + void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table); ++void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l); ++void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev); ++void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, ++ struct rtw_rx_pkt_stat *pkt_stat); ++void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev); + + struct rtw_txpwr_lmt_cfg_pair { + u8 regd; +@@ -109,7 +114,7 @@ const struct rtw_table name ## _tbl = { \ + + static inline const struct rtw_rfe_def *rtw_get_rfe_def(struct rtw_dev *rtwdev) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + const struct rtw_rfe_def *rfe_def = NULL; + +@@ -143,6 +148,7 @@ struct rtw_power_params { + s8 pwr_offset; + s8 pwr_limit; + s8 pwr_remnant; ++ s8 pwr_sar; + }; + + void +@@ -186,4 +192,7 @@ enum rtw_phy_cck_pd_lv { + #define LSSI_READ_EDGE_MASK 0x80000000 + #define LSSI_READ_DATA_MASK 0xfffff + ++#define RRSR_RATE_ORDER_MAX 0xfffff ++#define RRSR_RATE_ORDER_CCK_LEN 4 ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c +index 7a189a9926fe..15454dd27fff 100644 +--- a/drivers/net/wireless/realtek/rtw88/ps.c ++++ b/drivers/net/wireless/realtek/rtw88/ps.c +@@ -18,15 +18,16 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) + if (ret) + rtw_err(rtwdev, "leave idle state failed\n"); + ++ rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); + rtw_set_channel(rtwdev); +- clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags); + + return ret; + } + + int rtw_enter_ips(struct rtw_dev *rtwdev) + { +- set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags); ++ if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) ++ return 0; + + rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER); + +@@ -36,8 +37,7 @@ int rtw_enter_ips(struct rtw_dev *rtwdev) + return 0; + } + +-static void rtw_restore_port_cfg_iter(void *data, u8 *mac, +- struct ieee80211_vif *vif) ++static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif) + { + struct rtw_dev *rtwdev = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; +@@ -50,6 +50,9 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) + { + int ret; + ++ if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) ++ return 0; ++ + rtw_hci_link_ps(rtwdev, false); + + ret = rtw_ips_pwr_up(rtwdev); +@@ -58,9 +61,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) + return ret; + } + +- rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev); +- +- rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); ++ rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); + + return 0; + } +@@ -68,48 +69,42 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) + void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter) + { + u8 request, confirm, polling; +- u8 polling_cnt; +- u8 retry_cnt = 0; +- +- for (retry_cnt = 0; retry_cnt < 3; retry_cnt++) { +- request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); +- confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); +- +- /* toggle to request power mode, others remain 0 */ +- request ^= request | BIT_RPWM_TOGGLE; +- if (!enter) { +- request |= POWER_MODE_ACK; +- } else { +- request |= POWER_MODE_LCLK; +- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG) +- request |= POWER_MODE_PG; +- } +- +- rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request); +- +- if (enter) +- return; +- +- /* check confirm power mode has left power save state */ +- for (polling_cnt = 0; polling_cnt < 50; polling_cnt++) { +- polling = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); +- if ((polling ^ confirm) & BIT_RPWM_TOGGLE) +- return; +- udelay(100); +- } +- +- /* in case of fw/hw missed the request, retry */ +- rtw_warn(rtwdev, "failed to leave deep PS, retry=%d\n", +- retry_cnt); ++ int ret; ++ ++ request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); ++ confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); ++ ++ /* toggle to request power mode, others remain 0 */ ++ request ^= request | BIT_RPWM_TOGGLE; ++ if (enter) { ++ request |= POWER_MODE_LCLK; ++ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) ++ request |= POWER_MODE_PG; + } ++ /* Each request require an ack from firmware */ ++ request |= POWER_MODE_ACK; + +- /* Hit here means that driver failed to change hardware power mode to +- * active state after retry 3 times. If the power state is locked at +- * Deep sleep, most of the hardware circuits is not working, even +- * register read/write. It should be treated as fatal error and +- * requires an entire analysis about the firmware/hardware +- */ +- WARN(1, "Hardware power state locked\n"); ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) ++ request |= POWER_TX_WAKE; ++ ++ rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request); ++ ++ /* Check firmware get the power requset and ack via cpwm register */ ++ ret = read_poll_timeout_atomic(rtw_read8, polling, ++ (polling ^ confirm) & BIT_RPWM_TOGGLE, ++ 100, 15000, true, rtwdev, ++ rtwdev->hci.cpwm_addr); ++ if (ret) { ++ /* Hit here means that driver failed to get an ack from firmware. ++ * The reason could be that hardware is locked at Deep sleep, ++ * so most of the hardware circuits are not working, even ++ * register read/write; or firmware is locked in some state and ++ * cannot get the request. It should be treated as fatal error ++ * and requires an entire analysis about the firmware/hardware. ++ */ ++ WARN(1, "firmware failed to ack driver for %s Deep Power mode\n", ++ enter ? "entering" : "leaving"); ++ } + } + EXPORT_SYMBOL(rtw_power_mode_change); + +@@ -118,7 +113,7 @@ static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev) + rtw_hci_deep_ps(rtwdev, false); + } + +-static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev) ++static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev) + { + int i; + +@@ -136,12 +131,53 @@ static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev) + */ + for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) { + if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0) +- return; ++ return 0; + msleep(20); + } + +- rtw_write32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN, 0); +- rtw_warn(rtwdev, "firmware failed to restore hardware setting\n"); ++ return -EBUSY; ++} ++ ++static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev) ++{ ++ if (wait_for_completion_timeout(&rtwdev->lps_leave_check, ++ LEAVE_LPS_TIMEOUT)) ++ return 0; ++ return -EBUSY; ++} ++ ++static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev) ++{ ++ bool ret = false; ++ struct rtw_fw_state *fw; ++ ++ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) ++ fw = &rtwdev->wow_fw; ++ else ++ fw = &rtwdev->fw; ++ ++ if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) ++ ret = __rtw_fw_leave_lps_check_c2h(rtwdev); ++ else ++ ret = __rtw_fw_leave_lps_check_reg(rtwdev); ++ ++ if (ret) { ++ rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN); ++ rtw_warn(rtwdev, "firmware failed to leave lps state\n"); ++ } ++} ++ ++static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev) ++{ ++ struct rtw_fw_state *fw; ++ ++ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) ++ fw = &rtwdev->wow_fw; ++ else ++ fw = &rtwdev->fw; ++ ++ if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) ++ reinit_completion(&rtwdev->lps_leave_check); + } + + static void rtw_leave_lps_core(struct rtw_dev *rtwdev) +@@ -154,17 +190,26 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev) + conf->smart_ps = 0; + + rtw_hci_link_ps(rtwdev, false); ++ rtw_fw_leave_lps_check_prepare(rtwdev); + rtw_fw_set_pwr_mode(rtwdev); +- rtw_fw_leave_lps_state_check(rtwdev); ++ rtw_fw_leave_lps_check(rtwdev); + + clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); + + rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); + } + ++enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev) ++{ ++ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) ++ return rtwdev->lps_conf.wow_deep_mode; ++ else ++ return rtwdev->lps_conf.deep_mode; ++} ++ + static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev) + { +- if (rtwdev->lps_conf.deep_mode == LPS_DEEP_MODE_NONE) ++ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE) + return; + + if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) { +@@ -173,7 +218,7 @@ static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev) + return; + } + +- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG) ++ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) + rtw_fw_set_pg_info(rtwdev); + + rtw_hci_deep_ps(rtwdev, true); +@@ -252,3 +297,47 @@ void rtw_leave_lps_deep(struct rtw_dev *rtwdev) + + __rtw_leave_lps_deep(rtwdev); + } ++ ++struct rtw_vif_recalc_lps_iter_data { ++ struct rtw_dev *rtwdev; ++ struct ieee80211_vif *found_vif; ++ int count; ++}; ++ ++static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, ++ struct ieee80211_vif *vif) ++{ ++ if (data->count < 0) ++ return; ++ ++ if (vif->type != NL80211_IFTYPE_STATION) { ++ data->count = -1; ++ return; ++ } ++ ++ data->count++; ++ data->found_vif = vif; ++} ++ ++static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) ++{ ++ __rtw_vif_recalc_lps(data, vif); ++} ++ ++void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) ++{ ++ struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev }; ++ ++ if (new_vif) ++ __rtw_vif_recalc_lps(&data, new_vif); ++ rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++ if (data.count == 1 && data.found_vif->cfg.ps) { ++ rtwdev->ps_enabled = true; ++ } else { ++ rtwdev->ps_enabled = false; ++ rtw_leave_lps(rtwdev); ++ } ++#endif ++} +diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h +index 19afceca7d0e..5ae83d2526cf 100644 +--- a/drivers/net/wireless/realtek/rtw88/ps.h ++++ b/drivers/net/wireless/realtek/rtw88/ps.h +@@ -9,9 +9,11 @@ + + #define POWER_MODE_ACK BIT(6) + #define POWER_MODE_PG BIT(4) ++#define POWER_TX_WAKE BIT(1) + #define POWER_MODE_LCLK BIT(0) + + #define LEAVE_LPS_TRY_CNT 5 ++#define LEAVE_LPS_TIMEOUT msecs_to_jiffies(100) + + int rtw_enter_ips(struct rtw_dev *rtwdev); + int rtw_leave_ips(struct rtw_dev *rtwdev); +@@ -20,5 +22,7 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter); + void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id); + void rtw_leave_lps(struct rtw_dev *rtwdev); + void rtw_leave_lps_deep(struct rtw_dev *rtwdev); ++enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev); ++void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif); + + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index 9088bfb2a315..7c6c11d50ff3 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -60,7 +60,7 @@ + #define REG_GPIO_MUXCFG 0x0040 + #define BIT_FSPI_EN BIT(19) + #define BIT_EN_SIC BIT(12) +-#define BIT_BT_AOD_GPIO3 BIT(9) ++ + #define BIT_PO_BT_PTA_PINS BIT(9) + #define BIT_BT_PTA_EN BIT(5) + #define BIT_WLRFE_4_5_EN BIT(2) +@@ -87,6 +87,7 @@ + #define BIT_LTE_MUX_CTRL_PATH BIT(26) + #define REG_HCI_OPT_CTRL 0x0074 + #define BIT_USB_SUS_DIS BIT(8) ++#define BIT_SDIO_PAD_E5 BIT(18) + + #define REG_AFE_CTRL_4 0x0078 + #define BIT_CK320M_AFE_EN BIT(4) +@@ -129,6 +130,9 @@ + #define REG_MCU_TST_CFG 0x84 + #define VAL_FW_TRIGGER 0x1 + ++#define REG_PMC_DBG_CTRL1 0xa8 ++#define BITS_PMC_BT_IQK_STS GENMASK(22, 21) ++ + #define REG_EFUSE_ACCESS 0x00CF + #define EFUSE_ACCESS_ON 0x69 + #define EFUSE_ACCESS_OFF 0x00 +@@ -181,6 +185,10 @@ + #define BIT_TXDMA_VIQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) + #define REG_TXDMA_PQ_MAP 0x010C ++#define BIT_RXDMA_ARBBW_EN BIT(0) ++#define BIT_RXSHFT_EN BIT(1) ++#define BIT_RXDMA_AGG_EN BIT(2) ++#define BIT_TXDMA_BW_EN BIT(3) + #define BIT_SHIFT_TXDMA_BEQ_MAP 8 + #define BIT_MASK_TXDMA_BEQ_MAP 0x3 + #define BIT_TXDMA_BEQ_MAP(x) \ +@@ -279,10 +287,18 @@ + #define REG_H2C_TAIL 0x0248 + #define REG_H2C_READ_ADDR 0x024C + #define REG_H2C_INFO 0x0254 ++#define REG_RXDMA_AGG_PG_TH 0x0280 ++#define BIT_RXDMA_AGG_PG_TH GENMASK(7, 0) ++#define BIT_DMA_AGG_TO_V1 GENMASK(15, 8) ++#define BIT_EN_PRE_CALC BIT(29) + #define REG_RXPKT_NUM 0x0284 + #define BIT_RXDMA_REQ BIT(19) + #define BIT_RW_RELEASE BIT(18) + #define BIT_RXDMA_IDLE BIT(17) ++#define REG_RXDMA_STATUS 0x0288 ++#define REG_RXDMA_DPR 0x028C ++#define REG_RXDMA_MODE 0x0290 ++#define BIT_DMA_MODE BIT(1) + #define REG_RXPKTNUM 0x02B0 + + #define REG_INT_MIG 0x0304 +@@ -306,6 +322,8 @@ + #define REG_DARFRC 0x0430 + #define REG_DARFRCH 0x0434 + #define REG_RARFRCH 0x043C ++#define REG_RRSR 0x0440 ++#define BITS_RRSR_RSC GENMASK(22, 21) + #define REG_ARFR0 0x0444 + #define REG_ARFRH0 0x0448 + #define REG_ARFR1_V1 0x044C +@@ -356,9 +374,13 @@ + #define REG_AGGR_BREAK_TIME 0x051A + #define REG_SLOT 0x051B + #define REG_TX_PTCL_CTRL 0x0520 ++#define BIT_DIS_EDCCA BIT(15) + #define BIT_SIFS_BK_EN BIT(12) + #define REG_TXPAUSE 0x0522 ++#define BIT_AC_QUEUE GENMASK(7, 0) ++#define BIT_HIGH_QUEUE BIT(5) + #define REG_RD_CTRL 0x0524 ++#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11) + #define BIT_DIS_TXOP_CFE BIT(10) + #define BIT_DIS_LSIG_CFE BIT(9) + #define BIT_DIS_STBC_CFE BIT(8) +@@ -381,12 +403,15 @@ + #define BIT_EN_FREE_CNT BIT(3) + #define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1)) + #define REG_HIQ_NO_LMT_EN 0x5A7 ++#define REG_DTIM_COUNTER_ROOT 0x5A8 + #define BIT_HIQ_NO_LMT_EN_ROOT BIT(0) + #define REG_TIMER0_SRC_SEL 0x05B4 + #define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6)) + + #define REG_TCR 0x0604 + #define BIT_PWRMGT_HWDATA_EN BIT(7) ++#define BIT_TCR_UPDATE_TIMIE BIT(5) ++#define BIT_TCR_UPDATE_HGQMD BIT(4) + #define REG_RCR 0x0608 + #define BIT_APP_FCS BIT(31) + #define BIT_APP_MIC BIT(30) +@@ -464,11 +489,17 @@ + #define REG_BT_COEX_TABLE_H3 0x06CF + #define REG_BBPSF_CTRL 0x06DC + +-#define REG_BT_COEX_V2 0x0763 +-#define BIT_GNT_BT_POLARITY BIT(4) ++#define REG_BT_COEX_V2 0x0762 ++#define BIT_GNT_BT_POLARITY BIT(12) + #define BIT_LTE_COEX_EN BIT(7) ++#define REG_BT_COEX_ENH_INTR_CTRL 0x76E ++#define BIT_R_GRANTALL_WLMASK BIT(3) ++#define BIT_STATIS_BT_EN BIT(2) ++#define REG_BT_ACT_STATISTICS 0x0770 ++#define REG_BT_ACT_STATISTICS_1 0x0774 + #define REG_BT_STAT_CTRL 0x0778 + #define REG_BT_TDMA_TIME 0x0790 ++#define BIT_MASK_SAMPLE_RATE GENMASK(5, 0) + #define REG_LTR_IDLE_LATENCY 0x0798 + #define REG_LTR_ACTIVE_LATENCY 0x079C + #define REG_LTR_CTRL_BASIC 0x07A4 +@@ -484,6 +515,8 @@ + #define REG_2ND_CCA_CTRL 0x0976 + + #define REG_CCK0_FAREPORT 0xa2c ++#define BIT_CCK0_2RX BIT(18) ++#define BIT_CCK0_MRC BIT(22) + + #define REG_DIS_DPD 0x0a70 + #define DIS_DPD_MASK GENMASK(9, 0) +@@ -507,6 +540,7 @@ + #define BIT_RFE_BUF_EN BIT(3) + + #define REG_ANAPAR_XTAL_0 0x1040 ++#define BIT_XCAP_0 GENMASK(23, 10) + #define REG_CPU_DMEM_CON 0x1080 + #define BIT_WL_PLATFORM_RST BIT(16) + #define BIT_WL_SECURITY_CLK BIT(15) +@@ -525,6 +559,7 @@ + #define BIT_DDMACH0_OWN BIT(31) + #define BIT_DDMACH0_CHKSUM_EN BIT(29) + #define BIT_DDMACH0_CHKSUM_STS BIT(27) ++#define BIT_DDMACH0_DDMA_MODE BIT(26) + #define BIT_DDMACH0_RESET_CHKSUM_STS BIT(25) + #define BIT_DDMACH0_CHKSUM_CONT BIT(24) + #define BIT_MASK_DDMACH0_DLEN 0x3ffff +@@ -619,9 +654,15 @@ + #define REG_ANAPAR 0x1c30 + #define BIT_ANAPAR_BTPS BIT(22) + #define REG_RSTB_SEL 0x1c38 ++#define BIT_DAC_OFF_ENABLE BIT(4) ++#define BIT_PI_IGNORE_GNT_BT BIT(3) ++#define BIT_NOMASK_TXBT_ENABLE BIT(3) + + #define REG_HRCV_MSG 0x1cf + ++#define REG_EDCCA_REPORT 0x2d38 ++#define BIT_EDCCA_FLAG BIT(24) ++ + #define REG_IGN_GNTBT4 0x4160 + + #define RF_MODE 0x00 +@@ -630,10 +671,13 @@ + #define RF_WLSEL 0x02 + #define RF_DTXLOK 0x08 + #define RF_CFGCH 0x18 ++#define BIT_BAND GENMASK(18, 16) + #define RF_RCK 0x1d + #define RF_LUTWA 0x33 + #define RF_LUTWD1 0x3e + #define RF_LUTWD0 0x3f ++#define BIT_GAIN_EXT BIT(12) ++#define BIT_DATA_L GENMASK(11, 0) + #define RF_T_METER 0x42 + #define RF_BSPAD 0x54 + #define RF_GAINTX 0x56 +@@ -650,6 +694,7 @@ + #define RF_RCKD 0xde + #define RF_TXADBG 0xde + #define RF_LUTDBG 0xdf ++#define BIT_TXA_TANK BIT(4) + #define RF_LUTWE2 0xee + #define RF_LUTWE 0xef + +diff --git a/drivers/net/wireless/realtek/rtw88/regd.c b/drivers/net/wireless/realtek/rtw88/regd.c +index 69744dd65968..2f547cbcf6da 100644 +--- a/drivers/net/wireless/realtek/rtw88/regd.c ++++ b/drivers/net/wireless/realtek/rtw88/regd.c +@@ -7,288 +7,274 @@ + #include "debug.h" + #include "phy.h" + +-#define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _txpwr_regd) \ ++#define COUNTRY_REGD_ENT(_alpha2, _regd_2g, _regd_5g) \ + {.alpha2 = (_alpha2), \ +- .chplan = (_chplan), \ +- .txpwr_regd = (_txpwr_regd) \ ++ .txpwr_regd_2g = (_regd_2g), \ ++ .txpwr_regd_5g = (_regd_5g), \ + } + ++#define rtw_dbg_regd_dump(_dev, _msg, _args...) \ ++do { \ ++ struct rtw_dev *__d = (_dev); \ ++ const struct rtw_regd *__r = &__d->regd; \ ++ rtw_dbg(__d, RTW_DBG_REGD, _msg \ ++ "apply alpha2 %c%c, regd {%d, %d}, dfs_region %d\n",\ ++ ##_args, \ ++ __r->regulatory->alpha2[0], \ ++ __r->regulatory->alpha2[1], \ ++ __r->regulatory->txpwr_regd_2g, \ ++ __r->regulatory->txpwr_regd_5g, \ ++ __r->dfs_region); \ ++} while (0) ++ + /* If country code is not correctly defined in efuse, + * use worldwide country code and txpwr regd. + */ +-static const struct rtw_regulatory rtw_defined_chplan = +- COUNTRY_CHPLAN_ENT("00", RTW_CHPLAN_REALTEK_DEFINE, RTW_REGD_WW); +- +-static const struct rtw_regulatory all_chplan_map[] = { +- COUNTRY_CHPLAN_ENT("AD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AE", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AF", RTW_CHPLAN_ETSI1_ETSI4, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AG", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("AI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AN", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("AO", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AR", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("AS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("AT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("AU", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("AW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("AZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BB", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("BD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BH", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BM", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("BN", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BO", RTW_CHPLAN_WORLD_FCC7, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("BR", RTW_CHPLAN_FCC2_FCC1, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("BS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("BT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BV", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BW", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("BZ", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("CA", RTW_CHPLAN_IC1_IC2, RTW_REGD_IC), +- COUNTRY_CHPLAN_ENT("CC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CI", RTW_CHPLAN_ETSI1_ETSI4, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CL", RTW_CHPLAN_WORLD_CHILE1, RTW_REGD_CHILE), +- COUNTRY_CHPLAN_ENT("CM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CN", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CO", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("CR", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("CV", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CX", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("CY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("CZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("DE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("DJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("DK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("DM", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("DO", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("DZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("EC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("EE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("EG", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("EH", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ER", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ES", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ET", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("FI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("FJ", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("FK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("FM", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("FO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("FR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GD", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("GE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GP", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GT", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("GU", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("GW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("GY", RTW_CHPLAN_FCC1_NCC3, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("HK", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("HM", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("HN", RTW_CHPLAN_WORLD_FCC5, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("HR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("HT", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("HU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ID", RTW_CHPLAN_ETSI1_ETSI12, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IL", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IN", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("IT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("JE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("JM", RTW_CHPLAN_WORLD_FCC5, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("JO", RTW_CHPLAN_WORLD_ETSI8, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("JP", RTW_CHPLAN_MKK1_MKK1, RTW_REGD_MKK), +- COUNTRY_CHPLAN_ENT("KE", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KN", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("KR", RTW_CHPLAN_KCC1_KCC3, RTW_REGD_KCC), +- COUNTRY_CHPLAN_ENT("KW", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("KY", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("KZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("LI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LV", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("LY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MA", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ME", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MF", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("MG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MH", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("MK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ML", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MO", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MP", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("MQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MV", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MX", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("MY", RTW_CHPLAN_WORLD_ETSI15, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("MZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NF", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("NG", RTW_CHPLAN_WORLD_ETSI20, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NI", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("NL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NP", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("NU", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("NZ", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("OM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PA", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("PE", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("PF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PG", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PH", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PK", RTW_CHPLAN_WORLD_ETSI10, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PR", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("PT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("PW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("PY", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("QA", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("RE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("RO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("RS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("RU", RTW_CHPLAN_WORLD_ETSI14, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("RW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SA", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("SE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SG", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("SR", RTW_CHPLAN_FCC2_FCC17, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("ST", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("SV", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("SX", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("SZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TH", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TK", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ACMA), +- COUNTRY_CHPLAN_ENT("TM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TN", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TT", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("TV", RTW_CHPLAN_ETSI1_NULL, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("TW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("TZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("UA", RTW_CHPLAN_WORLD_ETSI3, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("UG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("US", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("UY", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("UZ", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("VA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("VC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("VE", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("VG", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("VI", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("VN", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("VU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("WF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("WS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), +- COUNTRY_CHPLAN_ENT("YE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("YT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ZA", RTW_CHPLAN_WORLD_ETSI2, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ZM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +- COUNTRY_CHPLAN_ENT("ZW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), ++static const struct rtw_regulatory rtw_reg_ww = ++ COUNTRY_REGD_ENT("00", RTW_REGD_WW, RTW_REGD_WW); ++ ++static const struct rtw_regulatory rtw_reg_map[] = { ++ COUNTRY_REGD_ENT("AD", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AG", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("AI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AN", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("AO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AQ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AR", RTW_REGD_MEXICO, RTW_REGD_MEXICO), ++ COUNTRY_REGD_ENT("AS", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("AT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("AU", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("AW", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("AZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BB", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("BD", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BJ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BM", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("BN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BO", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("BR", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("BS", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("BT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BV", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BW", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BY", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("BZ", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("CA", RTW_REGD_IC, RTW_REGD_IC), ++ COUNTRY_REGD_ENT("CC", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CD", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CL", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("CM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CO", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("CR", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("CV", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CX", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("CY", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("CZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("DE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("DJ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("DK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("DM", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("DO", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("DZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("EC", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("EE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("EG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("EH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ER", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ES", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ET", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("FI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("FJ", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("FK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("FM", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("FO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("FR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GB", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GD", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("GE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GP", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GQ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GT", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("GU", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("GW", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("GY", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("HK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("HM", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("HN", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("HR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("HT", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("HU", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ID", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IQ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("IT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("JE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("JM", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("JO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("JP", RTW_REGD_MKK, RTW_REGD_MKK), ++ COUNTRY_REGD_ENT("KE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KN", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("KR", RTW_REGD_KCC, RTW_REGD_KCC), ++ COUNTRY_REGD_ENT("KW", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("KY", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("KZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LB", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LC", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("LI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LU", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LV", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("LY", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MC", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MD", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ME", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MF", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("MG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MH", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("MK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ML", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MP", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("MQ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MU", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MV", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MW", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MX", RTW_REGD_MEXICO, RTW_REGD_MEXICO), ++ COUNTRY_REGD_ENT("MY", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("MZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NC", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NF", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("NG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NI", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("NL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NP", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("NU", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("NZ", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("OM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PA", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("PE", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("PF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PR", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("PS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("PW", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("PY", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("QA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("RE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("RO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("RS", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("RU", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("RW", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SB", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SC", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("SE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SI", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SJ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SL", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("SR", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("ST", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("SV", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("SX", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("SZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TC", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TD", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TH", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TJ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TK", RTW_REGD_ACMA, RTW_REGD_ACMA), ++ COUNTRY_REGD_ENT("TM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TO", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TR", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("TT", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("TV", RTW_REGD_ETSI, RTW_REGD_WW), ++ COUNTRY_REGD_ENT("TW", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("TZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("UA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("UG", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("US", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("UY", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("UZ", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("VA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("VC", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("VE", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("VG", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("VI", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("VN", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("VU", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("WF", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("WS", RTW_REGD_FCC, RTW_REGD_FCC), ++ COUNTRY_REGD_ENT("XK", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("YE", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("YT", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ZA", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ZM", RTW_REGD_ETSI, RTW_REGD_ETSI), ++ COUNTRY_REGD_ENT("ZW", RTW_REGD_ETSI, RTW_REGD_ETSI), + }; + +-static void rtw_regd_apply_beaconing_flags(struct wiphy *wiphy, +- enum nl80211_reg_initiator initiator) +-{ +- enum nl80211_band band; +- struct ieee80211_supported_band *sband; +- const struct ieee80211_reg_rule *reg_rule; +- struct ieee80211_channel *ch; +- unsigned int i; +- +- for (band = 0; band < NUM_NL80211_BANDS; band++) { +- if (!wiphy->bands[band]) +- continue; +- +- sband = wiphy->bands[band]; +- for (i = 0; i < sband->n_channels; i++) { +- ch = &sband->channels[i]; +- +- reg_rule = freq_reg_info(wiphy, +- MHZ_TO_KHZ(ch->center_freq)); +- if (IS_ERR(reg_rule)) +- continue; +- +- ch->flags &= ~IEEE80211_CHAN_DISABLED; +- +- if (!(reg_rule->flags & NL80211_RRF_NO_IR)) +- ch->flags &= ~IEEE80211_CHAN_NO_IR; +- } +- } +-} +- + static void rtw_regd_apply_hw_cap_flags(struct wiphy *wiphy) + { + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); +@@ -321,78 +307,225 @@ static void rtw_regd_apply_hw_cap_flags(struct wiphy *wiphy) + } + } + +-static void rtw_regd_apply_world_flags(struct wiphy *wiphy, +- enum nl80211_reg_initiator initiator) ++static bool rtw_reg_is_ww(const struct rtw_regulatory *reg) + { +- rtw_regd_apply_beaconing_flags(wiphy, initiator); ++ return reg == &rtw_reg_ww; + } + +-static struct rtw_regulatory rtw_regd_find_reg_by_name(char *alpha2) ++static bool rtw_reg_match(const struct rtw_regulatory *reg, const char *alpha2) ++{ ++ return memcmp(reg->alpha2, alpha2, 2) == 0; ++} ++ ++static const struct rtw_regulatory *rtw_reg_find_by_name(const char *alpha2) + { + unsigned int i; + +- for (i = 0; i < ARRAY_SIZE(all_chplan_map); i++) { +- if (!memcmp(all_chplan_map[i].alpha2, alpha2, 2)) +- return all_chplan_map[i]; ++ for (i = 0; i < ARRAY_SIZE(rtw_reg_map); i++) { ++ if (rtw_reg_match(&rtw_reg_map[i], alpha2)) ++ return &rtw_reg_map[i]; + } + +- return rtw_defined_chplan; ++ return &rtw_reg_ww; + } + +-static int rtw_regd_notifier_apply(struct rtw_dev *rtwdev, +- struct wiphy *wiphy, +- struct regulatory_request *request) ++static ++void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); ++ ++/* call this before ieee80211_register_hw() */ ++int rtw_regd_init(struct rtw_dev *rtwdev) + { +- if (request->initiator == NL80211_REGDOM_SET_BY_USER) +- return 0; +- rtwdev->regd = rtw_regd_find_reg_by_name(request->alpha2); +- rtw_regd_apply_world_flags(wiphy, request->initiator); ++ struct wiphy *wiphy = rtwdev->hw->wiphy; ++ const struct rtw_regulatory *chip_reg; + +- return 0; +-} ++ if (!wiphy) ++ return -EINVAL; + +-static int +-rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy, +- void (*reg_notifier)(struct wiphy *wiphy, +- struct regulatory_request *request)) +-{ +- wiphy->reg_notifier = reg_notifier; ++ wiphy->reg_notifier = rtw_regd_notifier; + +- wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG; +- wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; +- wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; ++ chip_reg = rtw_reg_find_by_name(rtwdev->efuse.country_code); ++ if (!rtw_reg_is_ww(chip_reg)) { ++ rtwdev->regd.state = RTW_REGD_STATE_PROGRAMMED; + +- rtw_regd_apply_hw_cap_flags(wiphy); ++ /* Set REGULATORY_STRICT_REG before ieee80211_register_hw(), ++ * stack will wait for regulatory_hint() and consider it ++ * as the superset for our regulatory rule. ++ */ ++ wiphy->regulatory_flags |= REGULATORY_STRICT_REG; ++ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; ++ } else { ++ rtwdev->regd.state = RTW_REGD_STATE_WORLDWIDE; ++ } + ++ rtwdev->regd.regulatory = &rtw_reg_ww; ++ rtwdev->regd.dfs_region = NL80211_DFS_UNSET; ++ rtw_dbg_regd_dump(rtwdev, "regd init state %d: ", rtwdev->regd.state); ++ ++ rtw_regd_apply_hw_cap_flags(wiphy); + return 0; + } + +-int rtw_regd_init(struct rtw_dev *rtwdev, +- void (*reg_notifier)(struct wiphy *wiphy, +- struct regulatory_request *request)) ++/* call this after ieee80211_register_hw() */ ++int rtw_regd_hint(struct rtw_dev *rtwdev) + { + struct wiphy *wiphy = rtwdev->hw->wiphy; ++ int ret; + + if (!wiphy) + return -EINVAL; + +- rtwdev->regd = rtw_regd_find_reg_by_name(rtwdev->efuse.country_code); +- rtw_regd_init_wiphy(&rtwdev->regd, wiphy, reg_notifier); ++ if (rtwdev->regd.state == RTW_REGD_STATE_PROGRAMMED) { ++ rtw_dbg(rtwdev, RTW_DBG_REGD, ++ "country domain %c%c is PGed on efuse", ++ rtwdev->efuse.country_code[0], ++ rtwdev->efuse.country_code[1]); ++ ++ ret = regulatory_hint(wiphy, rtwdev->efuse.country_code); ++ if (ret) { ++ rtw_warn(rtwdev, ++ "failed to hint regulatory: %d\n", ret); ++ return ret; ++ } ++ } + + return 0; + } + ++static bool rtw_regd_mgmt_worldwide(struct rtw_dev *rtwdev, ++ struct rtw_regd *next_regd, ++ struct regulatory_request *request) ++{ ++ struct wiphy *wiphy = rtwdev->hw->wiphy; ++ ++ next_regd->state = RTW_REGD_STATE_WORLDWIDE; ++ ++ if (request->initiator == NL80211_REGDOM_SET_BY_USER && ++ !rtw_reg_is_ww(next_regd->regulatory)) { ++ next_regd->state = RTW_REGD_STATE_SETTING; ++ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; ++ } ++ ++ return true; ++} ++ ++static bool rtw_regd_mgmt_programmed(struct rtw_dev *rtwdev, ++ struct rtw_regd *next_regd, ++ struct regulatory_request *request) ++{ ++ if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER && ++ rtw_reg_match(next_regd->regulatory, rtwdev->efuse.country_code)) { ++ next_regd->state = RTW_REGD_STATE_PROGRAMMED; ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool rtw_regd_mgmt_setting(struct rtw_dev *rtwdev, ++ struct rtw_regd *next_regd, ++ struct regulatory_request *request) ++{ ++ struct wiphy *wiphy = rtwdev->hw->wiphy; ++ ++ if (request->initiator != NL80211_REGDOM_SET_BY_USER) ++ return false; ++ ++ next_regd->state = RTW_REGD_STATE_SETTING; ++ ++ if (rtw_reg_is_ww(next_regd->regulatory)) { ++ next_regd->state = RTW_REGD_STATE_WORLDWIDE; ++ wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; ++ } ++ ++ return true; ++} ++ ++static bool (*const rtw_regd_handler[RTW_REGD_STATE_NR]) ++ (struct rtw_dev *, struct rtw_regd *, struct regulatory_request *) = { ++ [RTW_REGD_STATE_WORLDWIDE] = rtw_regd_mgmt_worldwide, ++ [RTW_REGD_STATE_PROGRAMMED] = rtw_regd_mgmt_programmed, ++ [RTW_REGD_STATE_SETTING] = rtw_regd_mgmt_setting, ++}; ++ ++static bool rtw_regd_state_hdl(struct rtw_dev *rtwdev, ++ struct rtw_regd *next_regd, ++ struct regulatory_request *request) ++{ ++ next_regd->regulatory = rtw_reg_find_by_name(request->alpha2); ++ next_regd->dfs_region = request->dfs_region; ++ return rtw_regd_handler[rtwdev->regd.state](rtwdev, next_regd, request); ++} ++ ++static + void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) + { + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw_dev *rtwdev = hw->priv; + struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_regd next_regd = {0}; ++ bool hdl; ++ ++ hdl = rtw_regd_state_hdl(rtwdev, &next_regd, request); ++ if (!hdl) { ++ rtw_dbg(rtwdev, RTW_DBG_REGD, ++ "regd state %d: ignore request %c%c of initiator %d\n", ++ rtwdev->regd.state, ++ request->alpha2[0], ++ request->alpha2[1], ++ request->initiator); ++ return; ++ } ++ ++ rtw_dbg(rtwdev, RTW_DBG_REGD, "regd state: %d -> %d\n", ++ rtwdev->regd.state, next_regd.state); + +- rtw_regd_notifier_apply(rtwdev, wiphy, request); +- rtw_dbg(rtwdev, RTW_DBG_REGD, +- "get alpha2 %c%c from initiator %d, mapping to chplan 0x%x, txregd %d\n", +- request->alpha2[0], request->alpha2[1], request->initiator, +- rtwdev->regd.chplan, rtwdev->regd.txpwr_regd); ++ mutex_lock(&rtwdev->mutex); ++ rtwdev->regd = next_regd; ++ rtw_dbg_regd_dump(rtwdev, "get alpha2 %c%c from initiator %d: ", ++ request->alpha2[0], ++ request->alpha2[1], ++ request->initiator); + ++ rtw_phy_adaptivity_set_mode(rtwdev); + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); ++ mutex_unlock(&rtwdev->mutex); ++} ++ ++u8 rtw_regd_get(struct rtw_dev *rtwdev) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 band = hal->current_band_type; ++ ++ return band == RTW_BAND_2G ? ++ rtwdev->regd.regulatory->txpwr_regd_2g : ++ rtwdev->regd.regulatory->txpwr_regd_5g; ++} ++EXPORT_SYMBOL(rtw_regd_get); ++ ++struct rtw_regd_alternative_t { ++ bool set; ++ u8 alt; ++}; ++ ++#define DECL_REGD_ALT(_regd, _regd_alt) \ ++ [(_regd)] = {.set = true, .alt = (_regd_alt)} ++ ++static const struct rtw_regd_alternative_t ++rtw_regd_alt[RTW_REGD_MAX] = { ++ DECL_REGD_ALT(RTW_REGD_IC, RTW_REGD_FCC), ++ DECL_REGD_ALT(RTW_REGD_KCC, RTW_REGD_ETSI), ++ DECL_REGD_ALT(RTW_REGD_ACMA, RTW_REGD_ETSI), ++ DECL_REGD_ALT(RTW_REGD_CHILE, RTW_REGD_FCC), ++ DECL_REGD_ALT(RTW_REGD_UKRAINE, RTW_REGD_ETSI), ++ DECL_REGD_ALT(RTW_REGD_MEXICO, RTW_REGD_FCC), ++ DECL_REGD_ALT(RTW_REGD_CN, RTW_REGD_ETSI), ++}; ++ ++bool rtw_regd_has_alt(u8 regd, u8 *regd_alt) ++{ ++ if (!rtw_regd_alt[regd].set) ++ return false; ++ ++ *regd_alt = rtw_regd_alt[regd].alt; ++ return true; + } +diff --git a/drivers/net/wireless/realtek/rtw88/regd.h b/drivers/net/wireless/realtek/rtw88/regd.h +index 5d4578331788..34cb13d0cd9e 100644 +--- a/drivers/net/wireless/realtek/rtw88/regd.h ++++ b/drivers/net/wireless/realtek/rtw88/regd.h +@@ -64,8 +64,8 @@ enum country_code_type { + COUNTRY_CODE_MAX + }; + +-int rtw_regd_init(struct rtw_dev *rtwdev, +- void (*reg_notifier)(struct wiphy *wiphy, +- struct regulatory_request *request)); +-void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); ++int rtw_regd_init(struct rtw_dev *rtwdev); ++int rtw_regd_hint(struct rtw_dev *rtwdev); ++u8 rtw_regd_get(struct rtw_dev *rtwdev); ++bool rtw_regd_has_alt(u8 regd, u8 *regd_alt); + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +index 3ddd170f1651..c575476a0020 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c +@@ -60,8 +60,8 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = { + #define WLAN_MAX_AGG_NR 0x0A + #define WLAN_AMPDU_MAX_TIME 0x1C + #define WLAN_ANT_SEL 0x82 +-#define WLAN_LTR_IDLE_LAT 0x883C883C +-#define WLAN_LTR_ACT_LAT 0x880B880B ++#define WLAN_LTR_IDLE_LAT 0x90039003 ++#define WLAN_LTR_ACT_LAT 0x883c883c + #define WLAN_LTR_CTRL1 0xCB004010 + #define WLAN_LTR_CTRL2 0x01233425 + +@@ -192,6 +192,7 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) + rtw_write32(rtwdev, REG_LTR_CTRL_BASIC + 4, WLAN_LTR_CTRL2); + + rtw_phy_init(rtwdev); ++ rtwdev->dm_info.cck_pd_default = rtw_read8(rtwdev, REG_CSRATIO) & 0x1f; + + rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN); + +@@ -209,6 +210,18 @@ static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse, + ether_addr_copy(efuse->addr, map->e.mac_addr); + } + ++static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8723d_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->u.mac_addr); ++} ++ ++static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8723d_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->s.mac_addr); ++} ++ + static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + { + struct rtw_efuse *efuse = &rtwdev->efuse; +@@ -238,6 +251,12 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + case RTW_HCI_TYPE_PCIE: + rtw8723de_efuse_parsing(efuse, map); + break; ++ case RTW_HCI_TYPE_USB: ++ rtw8723du_efuse_parsing(efuse, map); ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rtw8723ds_efuse_parsing(efuse, map); ++ break; + default: + /* unsupported now */ + return -ENOTSUPP; +@@ -1498,6 +1517,34 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev) + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n"); + } + ++static void rtw8723d_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 pd[CCK_PD_LV_MAX] = {3, 7, 13, 13, 13}; ++ u8 cck_n_rx; ++ ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n", ++ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl); ++ ++ if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl) ++ return; ++ ++ cck_n_rx = (rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_2RX) && ++ rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_MRC)) ? 2 : 1; ++ rtw_dbg(rtwdev, RTW_DBG_PHY, ++ "is_linked=%d, lv=%d, n_rx=%d, cs_ratio=0x%x, pd_th=0x%x, cck_fa_avg=%d\n", ++ rtw_is_assoc(rtwdev), new_lvl, cck_n_rx, ++ dm_info->cck_pd_default + new_lvl * 2, ++ pd[new_lvl], dm_info->cck_fa_avg); ++ ++ dm_info->cck_fa_avg = CCK_FA_AVG_RESET; ++ ++ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl; ++ rtw_write32_mask(rtwdev, REG_PWRTH, 0x3f0000, pd[new_lvl]); ++ rtw_write32_mask(rtwdev, REG_PWRTH2, 0x1f0000, ++ dm_info->cck_pd_default + new_lvl * 2); ++} ++ + /* for coex */ + static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev) + { +@@ -1506,14 +1553,14 @@ static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev) + + /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ +- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); ++ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); +- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); ++ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); +@@ -1916,6 +1963,26 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + ++static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */ ++ __le16 chksum = 0; ++ __le16 *data = (__le16 *)(txdesc); ++ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc; ++ ++ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM); ++ ++ while (words--) ++ chksum ^= *data++; ++ ++ chksum = ~chksum; ++ ++ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum), ++ RTW_TX_DESC_W7_TXDESC_CHECKSUM); ++} ++ + static struct rtw_chip_ops rtw8723d_ops = { + .phy_set_param = rtw8723d_phy_set_param, + .read_efuse = rtw8723d_read_efuse, +@@ -1931,10 +1998,12 @@ static struct rtw_chip_ops rtw8723d_ops = { + .efuse_grant = rtw8723d_efuse_grant, + .false_alarm_statistics = rtw8723d_false_alarm_statistics, + .phy_calibration = rtw8723d_phy_calibration, ++ .cck_pd_set = rtw8723d_phy_cck_pd_set, + .pwr_track = rtw8723d_pwr_track, + .config_bfee = NULL, + .set_gid_table = NULL, + .cfg_csi_rate = NULL, ++ .fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum, + + .coex_set_init = rtw8723d_coex_cfg_init, + .coex_set_ant_switch = NULL, +@@ -1949,19 +2018,19 @@ static struct rtw_chip_ops rtw8723d_ops = { + static const struct coex_table_para table_sant_8723d[] = { + {0xffffffff, 0xffffffff}, /* case-0 */ + {0x55555555, 0x55555555}, +- {0x65555555, 0x65555555}, ++ {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ +- {0xa5555555, 0xaaaa5aaa}, +- {0x6a5a5a5a, 0x5a5a5a5a}, ++ {0x6a5a5555, 0xaaaaaaaa}, ++ {0x6a5a56aa, 0x6a5a56aa}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x66555555, 0x5a5a5a5a}, +- {0x65555555, 0x6a5a5a5a}, /* case-10 */ +- {0x65555555, 0xfafafafa}, ++ {0x66555555, 0x6a5a5a5a}, /* case-10 */ ++ {0x66555555, 0x6a5a5aaa}, + {0x66555555, 0x5a5a5aaa}, +- {0x65555555, 0x5aaa5aaa}, +- {0x65555555, 0xaaaa5aaa}, ++ {0x66555555, 0x6aaa5aaa}, ++ {0x66555555, 0xaaaa5aaa}, + {0x66555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x6afa5afa}, +@@ -1970,38 +2039,41 @@ static const struct coex_table_para table_sant_8723d[] = { + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, +- {0xffffffff, 0x6a5a5a5a}, ++ {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x55555555}, +- {0xffffffff, 0x6a5a5aaa}, /* case-25 */ ++ {0xffffffff, 0x5a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, +- {0x55555555, 0x6a6a6a6a}, +- {0x656a656a, 0x656a656a} ++ {0x55555555, 0x6a5a6a5a}, ++ {0x66556655, 0x66556655}, ++ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */ ++ {0xffffffff, 0x5aaa5aaa}, ++ {0x56555555, 0x5a5a5aaa}, + }; + + /* Non-Shared-Antenna Coex Table */ + static const struct coex_table_para table_nsant_8723d[] = { + {0xffffffff, 0xffffffff}, /* case-100 */ + {0x55555555, 0x55555555}, +- {0x65555555, 0x65555555}, ++ {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-105 */ + {0x5afa5afa, 0x5afa5afa}, + {0x55555555, 0xfafafafa}, +- {0x65555555, 0xfafafafa}, +- {0x65555555, 0x5a5a5a5a}, +- {0x65555555, 0x6a5a5a5a}, /* case-110 */ +- {0x65555555, 0xaaaaaaaa}, ++ {0x66555555, 0xfafafafa}, ++ {0x66555555, 0x5a5a5a5a}, ++ {0x66555555, 0x6a5a5a5a}, /* case-110 */ ++ {0x66555555, 0xaaaaaaaa}, + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, +- {0xaaffffaa, 0xfafafafa}, /* case-115 */ ++ {0xffff55ff, 0xffff55ff}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, + {0xffffffff, 0x5afa5afa}, +- {0xffffffff, 0xaaaaaaaa},/* case-120 */ ++ {0xffffffff, 0xaaaaaaaa}, /* case-120 */ + {0x55ff55ff, 0x5afa5afa}, + {0x55ff55ff, 0xaaaaaaaa}, + {0x55ff55ff, 0x55ff55ff} +@@ -2009,31 +2081,31 @@ static const struct coex_table_para table_nsant_8723d[] = { + + /* Shared-Antenna TDMA */ + static const struct coex_tdma_para tdma_sant_8723d[] = { +- { {0x08, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ ++ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, +- { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */ +- { {0x61, 0x48, 0x03, 0x11, 0x10} }, ++ { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */ +- { {0x61, 0x10, 0x03, 0x11, 0x14} }, ++ { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, +- { {0x51, 0x10, 0x03, 0x10, 0x54} }, +- { {0x51, 0x10, 0x03, 0x10, 0x55} }, +- { {0x51, 0x10, 0x07, 0x10, 0x54} }, /* case-15 */ ++ { {0x51, 0x08, 0x03, 0x10, 0x54} }, ++ { {0x51, 0x08, 0x03, 0x10, 0x55} }, ++ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ + { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, +- { {0x51, 0x15, 0x03, 0x10, 0x50} }, /* case-20 */ ++ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */ + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, +- { {0x65, 0x10, 0x03, 0x11, 0x11} }, ++ { {0x65, 0x10, 0x03, 0x11, 0x10} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} }, + { {0x61, 0x08, 0x03, 0x11, 0x11} } +@@ -2041,7 +2113,7 @@ static const struct coex_tdma_para tdma_sant_8723d[] = { + + /* Non-Shared-Antenna TDMA */ + static const struct coex_tdma_para tdma_nsant_8723d[] = { +- { {0x00, 0x00, 0x00, 0x40, 0x01} }, /* case-100 */ ++ { {0x00, 0x00, 0x00, 0x00, 0x01} }, /* case-100 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, +@@ -2062,7 +2134,7 @@ static const struct coex_tdma_para tdma_nsant_8723d[] = { + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */ +- { {0x51, 0x08, 0x03, 0x10, 0x50} }, ++ { {0x51, 0x08, 0x03, 0x10, 0x50} } + }; + + /* rssi in percentage % (dbm = % - 100) */ +@@ -2668,7 +2740,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = { + {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, + }; + +-struct rtw_chip_info rtw8723d_hw_spec = { ++const struct rtw_chip_info rtw8723d_hw_spec = { + .ops = &rtw8723d_ops, + .id = RTW_CHIP_TYPE_8723D, + .fw_name = "rtw88/rtw8723d_fw.bin", +@@ -2682,12 +2754,13 @@ struct rtw_chip_info rtw8723d_hw_spec = { + .ptct_efuse_size = 96 + 1, + .txff_size = 32768, + .rxff_size = 16384, ++ .rsvd_drv_pg_num = 8, + .txgi_factor = 1, + .is_pwr_by_rate_dec = true, + .max_power_index = 0x3f, + .csi_buf_pg_num = 0, + .band = RTW_BAND_2G, +- .page_size = 128, ++ .page_size = TX_PAGE_SIZE, + .dig_min = 0x20, + .ht_supported = true, + .vht_supported = false, +@@ -2714,11 +2787,15 @@ struct rtw_chip_info rtw8723d_hw_spec = { + .rx_ldpc = false, + .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, + .iqk_threshold = 8, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, ++ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, + + .coex_para_ver = 0x2007022f, + .bt_desired_ver = 0x2f, + .scbd_support = true, + .new_scbd10_def = true, ++ .ble_hid_profile_support = false, ++ .wl_mimo_ps_support = false, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_RATIO, + .ant_isolation = 15, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h +index 7894d321cd7e..3642a2c7f80c 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h +@@ -41,6 +41,19 @@ struct rtw8723de_efuse { + u8 sub_device_id[2]; + }; + ++struct rtw8723du_efuse { ++ u8 res4[48]; /* 0xd0 */ ++ u8 vender_id[2]; /* 0x100 */ ++ u8 product_id[2]; /* 0x102 */ ++ u8 usb_option; /* 0x104 */ ++ u8 mac_addr[ETH_ALEN]; /* 0x107 */ ++}; ++ ++struct rtw8723ds_efuse { ++ u8 res4[0x4a]; /* 0xd0 */ ++ u8 mac_addr[ETH_ALEN]; /* 0x11a */ ++}; ++ + struct rtw8723d_efuse { + __le16 rtl_id; + u8 rsvd[2]; +@@ -69,9 +82,15 @@ struct rtw8723d_efuse { + u8 rfe_option; + u8 country_code[2]; + u8 res[3]; +- struct rtw8723de_efuse e; ++ union { ++ struct rtw8723de_efuse e; ++ struct rtw8723du_efuse u; ++ struct rtw8723ds_efuse s; ++ }; + }; + ++extern const struct rtw_chip_info rtw8723d_hw_spec; ++ + /* phy status page0 */ + #define GET_PHY_STAT_P0_PWDB(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) +@@ -163,6 +182,7 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) + #define REG_CCK0_SYS 0x0a00 + #define BIT_CCK_SIDE_BAND BIT(4) + #define REG_CCK_ANT_SEL_11N 0x0a04 ++#define REG_PWRTH 0x0a08 + #define REG_CCK_FA_RST_11N 0x0a2c + #define BIT_MASK_CCK_CNT_KEEP BIT(12) + #define BIT_MASK_CCK_CNT_EN BIT(13) +@@ -175,6 +195,8 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) + #define REG_CCK_CCA_CNT_11N 0x0a60 + #define BIT_MASK_CCK_FA_MSB GENMASK(7, 0) + #define BIT_MASK_CCK_FA_LSB GENMASK(15, 8) ++#define REG_PWRTH2 0x0aa8 ++#define REG_CSRATIO 0x0aaa + #define REG_OFDM_FA_HOLDC_11N 0x0c00 + #define BIT_MASK_OFDM_FA_KEEP BIT(31) + #define REG_BB_RX_PATH_11N 0x0c04 +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c +index c81eb4c33642..abbaafa32851 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8723de.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c +@@ -4,7 +4,8 @@ + + #include + #include +-#include "rtw8723de.h" ++#include "pci.h" ++#include "rtw8723d.h" + + static const struct pci_device_id rtw_8723de_id_table[] = { + { +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c +new file mode 100644 +index 000000000000..f1ffffe42c8e +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c +@@ -0,0 +1,41 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) Martin Blumenstingl ++ */ ++ ++#include ++#include "sdio_ids.h" ++#include ++#include "main.h" ++#include "rtw8723d.h" ++#include "sdio.h" ++ ++static const struct sdio_device_id rtw_8723ds_id_table[] = { ++ { ++ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, ++ SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT), ++ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, ++ }, ++ { ++ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, ++ SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT), ++ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table); ++ ++static struct sdio_driver rtw_8723ds_driver = { ++ .name = "rtw_8723ds", ++ .probe = rtw_sdio_probe, ++ .remove = rtw_sdio_remove, ++ .id_table = rtw_8723ds_id_table, ++ .drv = { ++ .pm = &rtw_sdio_pm_ops, ++ .shutdown = rtw_sdio_shutdown, ++ } ++}; ++module_sdio_driver(rtw_8723ds_driver); ++ ++MODULE_AUTHOR("Martin Blumenstingl "); ++MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723du.c b/drivers/net/wireless/realtek/rtw88/rtw8723du.c +new file mode 100644 +index 000000000000..322a805da76b +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8723du.c +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8723d.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8723du_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd723, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* 8723DU 1*1 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd611, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* Edimax EW-7611ULB V2 */ ++ { }, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8723du_id_table); ++ ++static int rtw8723du_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return rtw_usb_probe(intf, id); ++} ++ ++static struct usb_driver rtw_8723du_driver = { ++ .name = "rtw_8723du", ++ .id_table = rtw_8723du_id_table, ++ .probe = rtw8723du_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8723du_driver); ++ ++MODULE_AUTHOR("Hans Ulli Kroll "); ++MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index f9615f76f173..5f3a3a88c3d0 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -14,6 +14,11 @@ + #include "reg.h" + #include "debug.h" + #include "bf.h" ++#include "regd.h" ++ ++static const s8 lna_gain_table_0[8] = {22, 8, -6, -22, -31, -40, -46, -52}; ++static const s8 lna_gain_table_1[16] = {10, 6, 2, -2, -6, -10, -14, -17, ++ -20, -24, -28, -31, -34, -37, -40, -44}; + + static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse, + struct rtw8821c_efuse *map) +@@ -21,15 +26,35 @@ static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse, + ether_addr_copy(efuse->addr, map->e.mac_addr); + } + ++static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8821c_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->u.mac_addr); ++} ++ ++static void rtw8821cs_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8821c_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->s.mac_addr); ++} ++ ++enum rtw8821ce_rf_set { ++ SWITCH_TO_BTG, ++ SWITCH_TO_WLG, ++ SWITCH_TO_WLA, ++ SWITCH_TO_BT, ++}; ++ + static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + { ++ struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw8821c_efuse *map; + int i; + + map = (struct rtw8821c_efuse *)log_map; + +- efuse->rfe_option = map->rfe_option; ++ efuse->rfe_option = map->rfe_option & 0x1f; + efuse->rf_board_option = map->rf_board_option; + efuse->crystal_cap = map->xtal_k; + efuse->pa_type_2g = map->pa_type; +@@ -46,13 +71,35 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g; + efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g; + ++ hal->pkg_type = map->rfe_option & BIT(5) ? 1 : 0; ++ ++ switch (efuse->rfe_option) { ++ case 0x2: ++ case 0x4: ++ case 0x7: ++ case 0xa: ++ case 0xc: ++ case 0xf: ++ hal->rfe_btg = true; ++ break; ++ } ++ + for (i = 0; i < 4; i++) + efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i]; + ++ if (rtwdev->efuse.rfe_option == 2 || rtwdev->efuse.rfe_option == 4) ++ efuse->txpwr_idx_table[0].pwr_idx_2g = map->txpwr_idx_table[1].pwr_idx_2g; ++ + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtw8821ce_efuse_parsing(efuse, map); + break; ++ case RTW_HCI_TYPE_USB: ++ rtw8821cu_efuse_parsing(efuse, map); ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rtw8821cs_efuse_parsing(efuse, map); ++ break; + default: + /* unsupported now */ + return -ENOTSUPP; +@@ -110,6 +157,7 @@ static void rtw8821c_phy_bf_init(struct rtw_dev *rtwdev) + + static void rtw8821c_phy_set_param(struct rtw_dev *rtwdev) + { ++ struct rtw_hal *hal = &rtwdev->hal; + u8 crystal_cap, val; + + /* power on BB/RF domain */ +@@ -144,9 +192,9 @@ static void rtw8821c_phy_set_param(struct rtw_dev *rtwdev) + + /* post init after header files config */ + rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST); +- rtwdev->chip->ch_param[0] = rtw_read32_mask(rtwdev, REG_TXSF2, MASKDWORD); +- rtwdev->chip->ch_param[1] = rtw_read32_mask(rtwdev, REG_TXSF6, MASKDWORD); +- rtwdev->chip->ch_param[2] = rtw_read32_mask(rtwdev, REG_TXFILTER, MASKDWORD); ++ hal->ch_param[0] = rtw_read32_mask(rtwdev, REG_TXSF2, MASKDWORD); ++ hal->ch_param[1] = rtw_read32_mask(rtwdev, REG_TXSF6, MASKDWORD); ++ hal->ch_param[2] = rtw_read32_mask(rtwdev, REG_TXFILTER, MASKDWORD); + + rtw_phy_init(rtwdev); + rtwdev->dm_info.cck_pd_default = rtw_read8(rtwdev, REG_CSRATIO) & 0x1f; +@@ -208,7 +256,8 @@ static int rtw8821c_mac_init(struct rtw_dev *rtwdev) + rtw_write8(rtwdev, REG_TCR + 1, WLAN_TX_FUNC_CFG1); + rtw_write8(rtwdev, REG_ACKTO_CCK, 0x40); + rtw_write8_set(rtwdev, REG_WMAC_TRXPTCL_CTL_H, BIT(1)); +- rtw_write8_set(rtwdev, REG_SND_PTCL_CTRL, BIT(6)); ++ rtw_write8_set(rtwdev, REG_SND_PTCL_CTRL, ++ BIT_DIS_CHK_VHTSIGB_CRC); + rtw_write32(rtwdev, REG_WMAC_OPTION_FUNCTION + 8, WLAN_MAC_OPT_FUNC2); + rtw_write8(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, WLAN_MAC_OPT_NORM_FUNC1); + +@@ -224,8 +273,43 @@ static void rtw8821c_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) + rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr); + } + ++static void rtw8821c_switch_rf_set(struct rtw_dev *rtwdev, u8 rf_set) ++{ ++ u32 reg; ++ ++ rtw_write32_set(rtwdev, REG_DMEM_CTRL, BIT_WL_RST); ++ rtw_write32_set(rtwdev, REG_SYS_CTRL, BIT_FEN_EN); ++ ++ reg = rtw_read32(rtwdev, REG_RFECTL); ++ switch (rf_set) { ++ case SWITCH_TO_BTG: ++ reg |= B_BTG_SWITCH; ++ reg &= ~(B_CTRL_SWITCH | B_WL_SWITCH | B_WLG_SWITCH | ++ B_WLA_SWITCH); ++ rtw_write32_mask(rtwdev, REG_ENRXCCA, MASKBYTE2, BTG_CCA); ++ rtw_write32_mask(rtwdev, REG_ENTXCCK, MASKLWORD, BTG_LNA); ++ break; ++ case SWITCH_TO_WLG: ++ reg |= B_WL_SWITCH | B_WLG_SWITCH; ++ reg &= ~(B_BTG_SWITCH | B_CTRL_SWITCH | B_WLA_SWITCH); ++ rtw_write32_mask(rtwdev, REG_ENRXCCA, MASKBYTE2, WLG_CCA); ++ rtw_write32_mask(rtwdev, REG_ENTXCCK, MASKLWORD, WLG_LNA); ++ break; ++ case SWITCH_TO_WLA: ++ reg |= B_WL_SWITCH | B_WLA_SWITCH; ++ reg &= ~(B_BTG_SWITCH | B_CTRL_SWITCH | B_WLG_SWITCH); ++ break; ++ case SWITCH_TO_BT: ++ default: ++ break; ++ } ++ ++ rtw_write32(rtwdev, REG_RFECTL, reg); ++} ++ + static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) + { ++ struct rtw_hal *hal = &rtwdev->hal; + u32 rf_reg18; + + rf_reg18 = rtw_read_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK); +@@ -257,9 +341,14 @@ static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) + } + + if (channel <= 14) { ++ if (hal->rfe_btg) ++ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_BTG); ++ else ++ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, 0x64, 0xf, 0xf); + } else { ++ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLA); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x0); + } + +@@ -295,6 +384,7 @@ static void rtw8821c_set_channel_rxdfir(struct rtw_dev *rtwdev, u8 bw) + static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx) + { ++ struct rtw_hal *hal = &rtwdev->hal; + u32 val32; + + if (channel <= 14) { +@@ -311,11 +401,11 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, + rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x00003667); + } else { + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, +- rtwdev->chip->ch_param[0]); ++ hal->ch_param[0]); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, +- rtwdev->chip->ch_param[1] & MASKLWORD); ++ hal->ch_param[1] & MASKLWORD); + rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, +- rtwdev->chip->ch_param[2]); ++ hal->ch_param[2]); + } + } else if (channel > 35) { + rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x1); +@@ -426,22 +516,57 @@ static void rtw8821c_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw, + rtw8821c_set_channel_rxdfir(rtwdev, bw); + } + ++static s8 get_cck_rx_pwr(struct rtw_dev *rtwdev, u8 lna_idx, u8 vga_idx) ++{ ++ struct rtw_efuse *efuse = &rtwdev->efuse; ++ const s8 *lna_gain_table; ++ int lna_gain_table_size; ++ s8 rx_pwr_all = 0; ++ s8 lna_gain = 0; ++ ++ if (efuse->rfe_option == 0) { ++ lna_gain_table = lna_gain_table_0; ++ lna_gain_table_size = ARRAY_SIZE(lna_gain_table_0); ++ } else { ++ lna_gain_table = lna_gain_table_1; ++ lna_gain_table_size = ARRAY_SIZE(lna_gain_table_1); ++ } ++ ++ if (lna_idx >= lna_gain_table_size) { ++ rtw_warn(rtwdev, "incorrect lna index (%d)\n", lna_idx); ++ return -120; ++ } ++ ++ lna_gain = lna_gain_table[lna_idx]; ++ rx_pwr_all = lna_gain - 2 * vga_idx; ++ ++ return rx_pwr_all; ++} ++ + static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) + { +- s8 min_rx_power = -120; +- u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status); ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ s8 rx_power; ++ u8 lna_idx = 0; ++ u8 vga_idx = 0; ++ ++ vga_idx = GET_PHY_STAT_P0_VGA(phy_status); ++ lna_idx = FIELD_PREP(BIT_LNA_H_MASK, GET_PHY_STAT_P0_LNA_H(phy_status)) | ++ FIELD_PREP(BIT_LNA_L_MASK, GET_PHY_STAT_P0_LNA_L(phy_status)); ++ rx_power = get_cck_rx_pwr(rtwdev, lna_idx, vga_idx); + +- pkt_stat->rx_power[RF_PATH_A] = pwdb - 100; ++ pkt_stat->rx_power[RF_PATH_A] = rx_power; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); ++ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi; + pkt_stat->bw = RTW_CHANNEL_WIDTH_20; +- pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A], +- min_rx_power); ++ pkt_stat->signal_power = rx_power; + } + + static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) + { ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 rxsc, bw; + s8 min_rx_power = -120; + +@@ -461,6 +586,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + + pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); ++ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi; + pkt_stat->bw = bw; + pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A], + min_rx_power); +@@ -499,7 +625,8 @@ static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, + pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); + pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); + pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); +- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc); ++ pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && ++ GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; + pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); + pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); + pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); +@@ -579,9 +706,9 @@ static void rtw8821c_false_alarm_statistics(struct rtw_dev *rtwdev) + + dm_info->cck_fa_cnt = cck_fa_cnt; + dm_info->ofdm_fa_cnt = ofdm_fa_cnt; ++ dm_info->total_fa_cnt = ofdm_fa_cnt; + if (cck_enable) + dm_info->total_fa_cnt += cck_fa_cnt; +- dm_info->total_fa_cnt = ofdm_fa_cnt; + + crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK); + dm_info->cck_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); +@@ -656,8 +783,7 @@ static void rtw8821c_coex_cfg_init(struct rtw_dev *rtwdev) + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + + /* BT report packet sample rate */ +- rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, SAMPLE_RATE_MASK, +- SAMPLE_RATE); ++ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, BT_CNT_ENABLE); +@@ -691,6 +817,15 @@ static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, + if (switch_status == coex_dm->cur_switch_status) + return; + ++ if (coex_rfe->wlg_at_btg) { ++ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; ++ ++ if (coex_rfe->ant_switch_polarity) ++ pos_type = COEX_SWITCH_TO_WLA; ++ else ++ pos_type = COEX_SWITCH_TO_WLG_BT; ++ } ++ + coex_dm->cur_switch_status = switch_status; + + if (coex_rfe->ant_switch_diversity && +@@ -911,7 +1046,7 @@ static void rtw8821c_pwrtrack_set(struct rtw_dev *rtwdev) + s8 pwr_idx_offset_lower; + u8 channel = rtwdev->hal.current_channel; + u8 band_width = rtwdev->hal.current_band_width; +- u8 regd = rtwdev->regd.txpwr_regd; ++ u8 regd = rtw_regd_get(rtwdev); + u8 tx_rate = dm_info->tx_rate; + u8 max_pwr_idx = rtwdev->chip->max_power_index; + +@@ -1021,25 +1156,37 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) + { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 pd[CCK_PD_LV_MAX] = {3, 7, 13, 13, 13}; ++ u8 cck_n_rx; + +- if (dm_info->min_rssi > 60) { +- new_lvl = 4; +- pd[4] = 0x1d; +- goto set_cck_pd; +- } ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n", ++ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl); + + if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl) + return; + ++ cck_n_rx = (rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_2RX) && ++ rtw_read8_mask(rtwdev, REG_CCK0_FAREPORT, BIT_CCK0_MRC)) ? 2 : 1; ++ rtw_dbg(rtwdev, RTW_DBG_PHY, ++ "is_linked=%d, lv=%d, n_rx=%d, cs_ratio=0x%x, pd_th=0x%x, cck_fa_avg=%d\n", ++ rtw_is_assoc(rtwdev), new_lvl, cck_n_rx, ++ dm_info->cck_pd_default + new_lvl * 2, ++ pd[new_lvl], dm_info->cck_fa_avg); ++ + dm_info->cck_fa_avg = CCK_FA_AVG_RESET; + +-set_cck_pd: + dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl; + rtw_write32_mask(rtwdev, REG_PWRTH, 0x3f0000, pd[new_lvl]); + rtw_write32_mask(rtwdev, REG_PWRTH2, 0x1f0000, + dm_info->cck_pd_default + new_lvl * 2); + } + ++static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ fill_txdesc_checksum_common(txdesc, 16); ++} ++ + static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, +@@ -1410,6 +1557,9 @@ static const struct rtw_intf_phy_para_table phy_para_table_8821c = { + + static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { + [0] = RTW_DEF_RFE(8821c, 0, 0), ++ [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), ++ [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), ++ [6] = RTW_DEF_RFE(8821c, 0, 0), + }; + + static struct rtw_hw_reg rtw8821c_dig[] = { +@@ -1484,6 +1634,7 @@ static struct rtw_chip_ops rtw8821c_ops = { + .config_bfee = rtw8821c_bf_config_bfee, + .set_gid_table = rtw_bf_set_gid_table, + .cfg_csi_rate = rtw_bf_cfg_csi_rate, ++ .fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum, + + .coex_set_init = rtw8821c_coex_cfg_init, + .coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch, +@@ -1768,7 +1919,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = { + {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + }; + +-struct rtw_chip_info rtw8821c_hw_spec = { ++const struct rtw_chip_info rtw8821c_hw_spec = { + .ops = &rtw8821c_ops, + .id = RTW_CHIP_TYPE_8821C, + .fw_name = "rtw88/rtw8821c_fw.bin", +@@ -1782,12 +1933,13 @@ struct rtw_chip_info rtw8821c_hw_spec = { + .ptct_efuse_size = 96, + .txff_size = 65536, + .rxff_size = 16384, ++ .rsvd_drv_pg_num = 8, + .txgi_factor = 1, + .is_pwr_by_rate_dec = true, + .max_power_index = 0x3f, + .csi_buf_pg_num = 0, + .band = RTW_BAND_2G | RTW_BAND_5G, +- .page_size = 128, ++ .page_size = TX_PAGE_SIZE, + .dig_min = 0x1c, + .ht_supported = true, + .vht_supported = true, +@@ -1814,11 +1966,15 @@ struct rtw_chip_info rtw8821c_hw_spec = { + .iqk_threshold = 8, + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2, ++ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, + + .coex_para_ver = 0x19092746, + .bt_desired_ver = 0x46, + .scbd_support = true, + .new_scbd10_def = false, ++ .ble_hid_profile_support = false, ++ .wl_mimo_ps_support = false, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_RATIO, + .ant_isolation = 15, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +index 8d1e8ff71d7e..fcff31688c45 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +@@ -9,6 +9,26 @@ + + #define RCR_VHT_ACK BIT(26) + ++struct rtw8821cu_efuse { ++ u8 res4[4]; /* 0xd0 */ ++ u8 usb_optional_function; ++ u8 res5[0x1e]; ++ u8 res6[2]; ++ u8 serial[0x0b]; /* 0xf5 */ ++ u8 vid; /* 0x100 */ ++ u8 res7; ++ u8 pid; ++ u8 res8[4]; ++ u8 mac_addr[ETH_ALEN]; /* 0x107 */ ++ u8 res9[2]; ++ u8 vendor_name[0x07]; ++ u8 res10[2]; ++ u8 device_name[0x14]; ++ u8 res11[0xcf]; ++ u8 package_type; /* 0x1fb */ ++ u8 res12[0x4]; ++}; ++ + struct rtw8821ce_efuse { + u8 mac_addr[ETH_ALEN]; /* 0xd0 */ + u8 vender_id[2]; +@@ -45,6 +65,11 @@ struct rtw8821ce_efuse { + u8 res7; + }; + ++struct rtw8821cs_efuse { ++ u8 res4[0x4a]; /* 0xd0 */ ++ u8 mac_addr[ETH_ALEN]; /* 0x11a */ ++} __packed; ++ + struct rtw8821c_efuse { + __le16 rtl_id; + u8 res0[0x0e]; +@@ -73,6 +98,8 @@ struct rtw8821c_efuse { + u8 res[3]; + union { + struct rtw8821ce_efuse e; ++ struct rtw8821cu_efuse u; ++ struct rtw8821cs_efuse s; + }; + }; + +@@ -84,6 +111,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + rtw_write32_mask(rtwdev, addr + 0x200, mask, data); + } + ++extern const struct rtw_chip_info rtw8821c_hw_spec; ++ + #define rtw_write32s_mask(rtwdev, addr, mask, data) \ + do { \ + BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \ +@@ -148,6 +177,14 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + /* phy status page0 */ + #define GET_PHY_STAT_P0_PWDB(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) ++#define GET_PHY_STAT_P0_VGA(phy_stat) \ ++ le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(12, 8)) ++#define GET_PHY_STAT_P0_LNA_L(phy_stat) \ ++ le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(15, 13)) ++#define GET_PHY_STAT_P0_LNA_H(phy_stat) \ ++ le32_get_bits(*((__le32 *)(phy_stat) + 0x03), BIT(23)) ++#define BIT_LNA_H_MASK BIT(3) ++#define BIT_LNA_L_MASK GENMASK(2, 0) + + /* phy status page1 */ + #define GET_PHY_STAT_P1_PWDB_A(phy_stat) \ +@@ -173,6 +210,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8)) + ++#define REG_SYS_CTRL 0x000 ++#define BIT_FEN_EN BIT(26) + #define REG_INIRTS_RATE_SEL 0x0480 + #define REG_HTSTFWT 0x800 + #define REG_RXPSEL 0x808 +@@ -204,6 +243,11 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_FA_CCK 0xa5c + #define REG_RXDESC 0xa2c + #define REG_ENTXCCK 0xa80 ++#define BTG_LNA 0xfc84 ++#define WLG_LNA 0x7532 ++#define REG_ENRXCCA 0xa84 ++#define BTG_CCA 0x0e ++#define WLG_CCA 0x12 + #define REG_PWRTH2 0xaa8 + #define REG_CSRATIO 0xaaa + #define REG_TXFILTER 0xaac +@@ -217,6 +261,11 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_RFESEL0 0xcb0 + #define REG_RFESEL8 0xcb4 + #define REG_RFECTL 0xcb8 ++#define B_BTG_SWITCH BIT(16) ++#define B_CTRL_SWITCH BIT(18) ++#define B_WL_SWITCH (BIT(20) | BIT(22)) ++#define B_WLG_SWITCH BIT(21) ++#define B_WLA_SWITCH BIT(23) + #define REG_RFEINV 0xcbc + #define REG_AGCTR_B 0xe08 + #define REG_RXIGI_B 0xe50 +@@ -227,12 +276,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_CCA_OFDM 0xf08 + #define REG_FA_OFDM 0xf48 + #define REG_CCA_CCK 0xfcc ++#define REG_DMEM_CTRL 0x1080 ++#define BIT_WL_RST BIT(16) + #define REG_ANTWT 0x1904 + #define REG_IQKFAILMSK 0x1bf0 + #define BIT_MASK_R_RFE_SEL_15 GENMASK(31, 28) + #define BIT_SDIO_INT BIT(18) +-#define SAMPLE_RATE_MASK GENMASK(5, 0) +-#define SAMPLE_RATE 0x5 + #define BT_CNT_ENABLE 0x1 + #define BIT_BCN_QUEUE BIT(3) + #define BCN_PRI_EN 0x1 +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c +index 970f903f7dc7..6c82c4383497 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c +@@ -13,7 +13,7 @@ static const u32 rtw8821c_mac[] = { + 0x04F, 0x00000001, + 0x029, 0x000000F9, + 0x420, 0x00000080, +- 0x421, 0x0000000F, ++ 0x421, 0x0000001F, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, +@@ -1342,6 +1342,399 @@ static const u32 rtw8821c_agc[] = { + + RTW_DECL_TABLE_PHY_COND(rtw8821c_agc, rtw_phy_cfg_agc); + ++static const u32 rtw8821c_agc_btg_type2[] = { ++ 0x80001004, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFF000013, ++ 0x81C, 0xFE020013, ++ 0x81C, 0xFD040013, ++ 0x81C, 0xFC060013, ++ 0x81C, 0xFB080013, ++ 0x81C, 0xFA0A0013, ++ 0x81C, 0xF90C0013, ++ 0x81C, 0xF80E0013, ++ 0x81C, 0xF7100013, ++ 0x81C, 0xF6120013, ++ 0x81C, 0xF5140013, ++ 0x81C, 0xF4160013, ++ 0x81C, 0xF3180013, ++ 0x81C, 0xF21A0013, ++ 0x81C, 0xF11C0013, ++ 0x81C, 0xF01E0013, ++ 0x81C, 0xEF200013, ++ 0x81C, 0xEE220013, ++ 0x81C, 0xED240013, ++ 0x81C, 0xEC260013, ++ 0x81C, 0xEB280013, ++ 0x81C, 0xEA2A0013, ++ 0x81C, 0xE92C0013, ++ 0x81C, 0xE82E0013, ++ 0x81C, 0xE7300013, ++ 0x81C, 0x8B320013, ++ 0x81C, 0x8A340013, ++ 0x81C, 0x89360013, ++ 0x81C, 0x88380013, ++ 0x81C, 0x873A0013, ++ 0x81C, 0x863C0013, ++ 0x81C, 0x853E0013, ++ 0x81C, 0x84400013, ++ 0x81C, 0x83420013, ++ 0x81C, 0x82440013, ++ 0x81C, 0x81460013, ++ 0x81C, 0x08480013, ++ 0x81C, 0x074A0013, ++ 0x81C, 0x064C0013, ++ 0x81C, 0x054E0013, ++ 0x81C, 0x04500013, ++ 0x81C, 0x03520013, ++ 0x81C, 0x88540003, ++ 0x81C, 0x87560003, ++ 0x81C, 0x86580003, ++ 0x81C, 0x855A0003, ++ 0x81C, 0x845C0003, ++ 0x81C, 0x835E0003, ++ 0x81C, 0x82600003, ++ 0x81C, 0x81620003, ++ 0x81C, 0x07640003, ++ 0x81C, 0x06660003, ++ 0x81C, 0x05680003, ++ 0x81C, 0x046A0003, ++ 0x81C, 0x036C0003, ++ 0x81C, 0x026E0003, ++ 0x81C, 0x01700003, ++ 0x81C, 0x01720003, ++ 0x81C, 0x01740003, ++ 0x81C, 0x01760003, ++ 0x81C, 0x01780003, ++ 0x81C, 0x017A0003, ++ 0x81C, 0x017C0003, ++ 0x81C, 0x017E0003, ++ 0x81C, 0xFF000813, ++ 0x81C, 0xFE020813, ++ 0x81C, 0xFD040813, ++ 0x81C, 0xFC060813, ++ 0x81C, 0xFB080813, ++ 0x81C, 0xFA0A0813, ++ 0x81C, 0xF90C0813, ++ 0x81C, 0xF80E0813, ++ 0x81C, 0xF7100813, ++ 0x81C, 0xF6120813, ++ 0x81C, 0xF5140813, ++ 0x81C, 0xF4160813, ++ 0x81C, 0xF3180813, ++ 0x81C, 0xF21A0813, ++ 0x81C, 0xF11C0813, ++ 0x81C, 0x941E0813, ++ 0x81C, 0x93200813, ++ 0x81C, 0x92220813, ++ 0x81C, 0x91240813, ++ 0x81C, 0x90260813, ++ 0x81C, 0x8F280813, ++ 0x81C, 0x8E2A0813, ++ 0x81C, 0x8D2C0813, ++ 0x81C, 0x8C2E0813, ++ 0x81C, 0x8B300813, ++ 0x81C, 0x8A320813, ++ 0x81C, 0x89340813, ++ 0x81C, 0x88360813, ++ 0x81C, 0x87380813, ++ 0x81C, 0x863A0813, ++ 0x81C, 0x853C0813, ++ 0x81C, 0x843E0813, ++ 0x81C, 0x83400813, ++ 0x81C, 0x82420813, ++ 0x81C, 0x81440813, ++ 0x81C, 0x07460813, ++ 0x81C, 0x06480813, ++ 0x81C, 0x054A0813, ++ 0x81C, 0x044C0813, ++ 0x81C, 0x034E0813, ++ 0x81C, 0x02500813, ++ 0x81C, 0x01520813, ++ 0x81C, 0x88540803, ++ 0x81C, 0x87560803, ++ 0x81C, 0x86580803, ++ 0x81C, 0x855A0803, ++ 0x81C, 0x845C0803, ++ 0x81C, 0x835E0803, ++ 0x81C, 0x82600803, ++ 0x81C, 0x81620803, ++ 0x81C, 0x07640803, ++ 0x81C, 0x06660803, ++ 0x81C, 0x05680803, ++ 0x81C, 0x046A0803, ++ 0x81C, 0x036C0803, ++ 0x81C, 0x026E0803, ++ 0x81C, 0x01700803, ++ 0x81C, 0x01720803, ++ 0x81C, 0x01740803, ++ 0x81C, 0x01760803, ++ 0x81C, 0x01780803, ++ 0x81C, 0x017A0803, ++ 0x81C, 0x017C0803, ++ 0x81C, 0x017E0803, ++ 0x90001005, 0x00000000, 0x40000000, 0x00000000, ++ 0x81C, 0xFF000013, ++ 0x81C, 0xFE020013, ++ 0x81C, 0xFD040013, ++ 0x81C, 0xFC060013, ++ 0x81C, 0xFB080013, ++ 0x81C, 0xFA0A0013, ++ 0x81C, 0xF90C0013, ++ 0x81C, 0xF80E0013, ++ 0x81C, 0xF7100013, ++ 0x81C, 0xF6120013, ++ 0x81C, 0xF5140013, ++ 0x81C, 0xF4160013, ++ 0x81C, 0xF3180013, ++ 0x81C, 0xF21A0013, ++ 0x81C, 0xF11C0013, ++ 0x81C, 0xF01E0013, ++ 0x81C, 0xEF200013, ++ 0x81C, 0xEE220013, ++ 0x81C, 0xED240013, ++ 0x81C, 0xEC260013, ++ 0x81C, 0xEB280013, ++ 0x81C, 0xEA2A0013, ++ 0x81C, 0xE92C0013, ++ 0x81C, 0xE82E0013, ++ 0x81C, 0xE7300013, ++ 0x81C, 0x8B320013, ++ 0x81C, 0x8A340013, ++ 0x81C, 0x89360013, ++ 0x81C, 0x88380013, ++ 0x81C, 0x873A0013, ++ 0x81C, 0x863C0013, ++ 0x81C, 0x853E0013, ++ 0x81C, 0x84400013, ++ 0x81C, 0x83420013, ++ 0x81C, 0x82440013, ++ 0x81C, 0x81460013, ++ 0x81C, 0x08480013, ++ 0x81C, 0x074A0013, ++ 0x81C, 0x064C0013, ++ 0x81C, 0x054E0013, ++ 0x81C, 0x04500013, ++ 0x81C, 0x03520013, ++ 0x81C, 0x88540003, ++ 0x81C, 0x87560003, ++ 0x81C, 0x86580003, ++ 0x81C, 0x855A0003, ++ 0x81C, 0x845C0003, ++ 0x81C, 0x835E0003, ++ 0x81C, 0x82600003, ++ 0x81C, 0x81620003, ++ 0x81C, 0x07640003, ++ 0x81C, 0x06660003, ++ 0x81C, 0x05680003, ++ 0x81C, 0x046A0003, ++ 0x81C, 0x036C0003, ++ 0x81C, 0x026E0003, ++ 0x81C, 0x01700003, ++ 0x81C, 0x01720003, ++ 0x81C, 0x01740003, ++ 0x81C, 0x01760003, ++ 0x81C, 0x01780003, ++ 0x81C, 0x017A0003, ++ 0x81C, 0x017C0003, ++ 0x81C, 0x017E0003, ++ 0x81C, 0xFF000813, ++ 0x81C, 0xFE020813, ++ 0x81C, 0xFD040813, ++ 0x81C, 0xFC060813, ++ 0x81C, 0xFB080813, ++ 0x81C, 0xFA0A0813, ++ 0x81C, 0xF90C0813, ++ 0x81C, 0xF80E0813, ++ 0x81C, 0xF7100813, ++ 0x81C, 0xF6120813, ++ 0x81C, 0xF5140813, ++ 0x81C, 0xF4160813, ++ 0x81C, 0xF3180813, ++ 0x81C, 0xF21A0813, ++ 0x81C, 0xF11C0813, ++ 0x81C, 0x941E0813, ++ 0x81C, 0x93200813, ++ 0x81C, 0x92220813, ++ 0x81C, 0x91240813, ++ 0x81C, 0x90260813, ++ 0x81C, 0x8F280813, ++ 0x81C, 0x8E2A0813, ++ 0x81C, 0x8D2C0813, ++ 0x81C, 0x8C2E0813, ++ 0x81C, 0x8B300813, ++ 0x81C, 0x8A320813, ++ 0x81C, 0x89340813, ++ 0x81C, 0x88360813, ++ 0x81C, 0x87380813, ++ 0x81C, 0x863A0813, ++ 0x81C, 0x853C0813, ++ 0x81C, 0x843E0813, ++ 0x81C, 0x83400813, ++ 0x81C, 0x82420813, ++ 0x81C, 0x81440813, ++ 0x81C, 0x07460813, ++ 0x81C, 0x06480813, ++ 0x81C, 0x054A0813, ++ 0x81C, 0x044C0813, ++ 0x81C, 0x034E0813, ++ 0x81C, 0x02500813, ++ 0x81C, 0x01520813, ++ 0x81C, 0x88540803, ++ 0x81C, 0x87560803, ++ 0x81C, 0x86580803, ++ 0x81C, 0x855A0803, ++ 0x81C, 0x845C0803, ++ 0x81C, 0x835E0803, ++ 0x81C, 0x82600803, ++ 0x81C, 0x81620803, ++ 0x81C, 0x07640803, ++ 0x81C, 0x06660803, ++ 0x81C, 0x05680803, ++ 0x81C, 0x046A0803, ++ 0x81C, 0x036C0803, ++ 0x81C, 0x026E0803, ++ 0x81C, 0x01700803, ++ 0x81C, 0x01720803, ++ 0x81C, 0x01740803, ++ 0x81C, 0x01760803, ++ 0x81C, 0x01780803, ++ 0x81C, 0x017A0803, ++ 0x81C, 0x017C0803, ++ 0x81C, 0x017E0803, ++ 0xA0000000, 0x00000000, ++ 0x81C, 0xFF000013, ++ 0x81C, 0xFE020013, ++ 0x81C, 0xFD040013, ++ 0x81C, 0xFC060013, ++ 0x81C, 0xFB080013, ++ 0x81C, 0xFA0A0013, ++ 0x81C, 0xF90C0013, ++ 0x81C, 0xF80E0013, ++ 0x81C, 0xF7100013, ++ 0x81C, 0xF6120013, ++ 0x81C, 0xF5140013, ++ 0x81C, 0xF4160013, ++ 0x81C, 0xF3180013, ++ 0x81C, 0xF21A0013, ++ 0x81C, 0xF11C0013, ++ 0x81C, 0xF01E0013, ++ 0x81C, 0xEF200013, ++ 0x81C, 0xEE220013, ++ 0x81C, 0xED240013, ++ 0x81C, 0xEC260013, ++ 0x81C, 0xEB280013, ++ 0x81C, 0xEA2A0013, ++ 0x81C, 0xE92C0013, ++ 0x81C, 0xE82E0013, ++ 0x81C, 0xE7300013, ++ 0x81C, 0x8A320013, ++ 0x81C, 0x89340013, ++ 0x81C, 0x88360013, ++ 0x81C, 0x87380013, ++ 0x81C, 0x863A0013, ++ 0x81C, 0x853C0013, ++ 0x81C, 0x843E0013, ++ 0x81C, 0x83400013, ++ 0x81C, 0x82420013, ++ 0x81C, 0x81440013, ++ 0x81C, 0x07460013, ++ 0x81C, 0x06480013, ++ 0x81C, 0x054A0013, ++ 0x81C, 0x044C0013, ++ 0x81C, 0x034E0013, ++ 0x81C, 0x02500013, ++ 0x81C, 0x01520013, ++ 0x81C, 0x88540003, ++ 0x81C, 0x87560003, ++ 0x81C, 0x86580003, ++ 0x81C, 0x855A0003, ++ 0x81C, 0x845C0003, ++ 0x81C, 0x835E0003, ++ 0x81C, 0x82600003, ++ 0x81C, 0x81620003, ++ 0x81C, 0x07640003, ++ 0x81C, 0x06660003, ++ 0x81C, 0x05680003, ++ 0x81C, 0x046A0003, ++ 0x81C, 0x036C0003, ++ 0x81C, 0x026E0003, ++ 0x81C, 0x01700003, ++ 0x81C, 0x01720003, ++ 0x81C, 0x01740003, ++ 0x81C, 0x01760003, ++ 0x81C, 0x01780003, ++ 0x81C, 0x017A0003, ++ 0x81C, 0x017C0003, ++ 0x81C, 0x017E0003, ++ 0x81C, 0xFF000813, ++ 0x81C, 0xFE020813, ++ 0x81C, 0xFD040813, ++ 0x81C, 0xFC060813, ++ 0x81C, 0xFB080813, ++ 0x81C, 0xFA0A0813, ++ 0x81C, 0xF90C0813, ++ 0x81C, 0xF80E0813, ++ 0x81C, 0xF7100813, ++ 0x81C, 0xF6120813, ++ 0x81C, 0xF5140813, ++ 0x81C, 0xF4160813, ++ 0x81C, 0xF3180813, ++ 0x81C, 0xF21A0813, ++ 0x81C, 0xF11C0813, ++ 0x81C, 0x961E0813, ++ 0x81C, 0x95200813, ++ 0x81C, 0x94220813, ++ 0x81C, 0x93240813, ++ 0x81C, 0x92260813, ++ 0x81C, 0x91280813, ++ 0x81C, 0x8F2A0813, ++ 0x81C, 0x8E2C0813, ++ 0x81C, 0x8D2E0813, ++ 0x81C, 0x8C300813, ++ 0x81C, 0x8B320813, ++ 0x81C, 0x8A340813, ++ 0x81C, 0x89360813, ++ 0x81C, 0x88380813, ++ 0x81C, 0x873A0813, ++ 0x81C, 0x863C0813, ++ 0x81C, 0x853E0813, ++ 0x81C, 0x84400813, ++ 0x81C, 0x83420813, ++ 0x81C, 0x82440813, ++ 0x81C, 0x08460813, ++ 0x81C, 0x07480813, ++ 0x81C, 0x064A0813, ++ 0x81C, 0x054C0813, ++ 0x81C, 0x044E0813, ++ 0x81C, 0x03500813, ++ 0x81C, 0x02520813, ++ 0x81C, 0x89540803, ++ 0x81C, 0x88560803, ++ 0x81C, 0x87580803, ++ 0x81C, 0x865A0803, ++ 0x81C, 0x855C0803, ++ 0x81C, 0x845E0803, ++ 0x81C, 0x83600803, ++ 0x81C, 0x82620803, ++ 0x81C, 0x07640803, ++ 0x81C, 0x06660803, ++ 0x81C, 0x05680803, ++ 0x81C, 0x046A0803, ++ 0x81C, 0x036C0803, ++ 0x81C, 0x026E0803, ++ 0x81C, 0x01700803, ++ 0x81C, 0x01720803, ++ 0x81C, 0x01740803, ++ 0x81C, 0x01760803, ++ 0x81C, 0x01780803, ++ 0x81C, 0x017A0803, ++ 0x81C, 0x017C0803, ++ 0x81C, 0x017E0803, ++ 0xB0000000, 0x00000000, ++}; ++ ++RTW_DECL_TABLE_PHY_COND(rtw8821c_agc_btg_type2, rtw_phy_cfg_agc); ++ + static const u32 rtw8821c_bb[] = { + 0x800, 0x9020D010, + 0x804, 0x80018180, +@@ -1394,7 +1787,11 @@ static const u32 rtw8821c_bb[] = { + 0x8C0, 0xFFE04020, + 0x8C4, 0x47C00000, + 0x8C8, 0x00025165, ++ 0x82000400, 0x00000000, 0x40000000, 0x00000000, ++ 0x8CC, 0x08190492, ++ 0xA0000000, 0x00000000, + 0x8CC, 0x08188492, ++ 0xB0000000, 0x00000000, + 0x8D0, 0x0000B800, + 0x8D4, 0x860308A0, + 0x8D8, 0x290B5612, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.h b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.h +index 5ea8b4fc7fba..cda98f5c4a01 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.h +@@ -7,6 +7,7 @@ + + extern const struct rtw_table rtw8821c_mac_tbl; + extern const struct rtw_table rtw8821c_agc_tbl; ++extern const struct rtw_table rtw8821c_agc_btg_type2_tbl; + extern const struct rtw_table rtw8821c_bb_tbl; + extern const struct rtw_table rtw8821c_bb_pg_type0_tbl; + extern const struct rtw_table rtw8821c_rf_a_tbl; +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c +index 616fdcfd62c9..f3d971feda04 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c +@@ -4,9 +4,14 @@ + + #include + #include +-#include "rtw8821ce.h" ++#include "pci.h" ++#include "rtw8821c.h" + + static const struct pci_device_id rtw_8821ce_id_table[] = { ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB821), ++ .driver_data = (kernel_ulong_t)&rtw8821c_hw_spec ++ }, + { + PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC821), + .driver_data = (kernel_ulong_t)&rtw8821c_hw_spec +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c +new file mode 100644 +index 000000000000..649f41baa064 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) Martin Blumenstingl ++ */ ++ ++#include ++#include "sdio_ids.h" ++#include ++#include "main.h" ++#include "rtw8821c.h" ++#include "sdio.h" ++ ++static const struct sdio_device_id rtw_8821cs_id_table[] = { ++ { ++ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, ++ SDIO_DEVICE_ID_REALTEK_RTW8821CS), ++ .driver_data = (kernel_ulong_t)&rtw8821c_hw_spec, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(sdio, rtw_8821cs_id_table); ++ ++static struct sdio_driver rtw_8821cs_driver = { ++ .name = "rtw_8821cs", ++ .probe = rtw_sdio_probe, ++ .remove = rtw_sdio_remove, ++ .id_table = rtw_8821cs_id_table, ++ .drv = { ++ .pm = &rtw_sdio_pm_ops, ++ .shutdown = rtw_sdio_shutdown, ++ } ++}; ++module_sdio_driver(rtw_8821cs_driver); ++ ++MODULE_AUTHOR("Martin Blumenstingl "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cs driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +new file mode 100644 +index 000000000000..e2c7d9f87683 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +@@ -0,0 +1,62 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8821c.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8821cu_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8731, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc80c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331d, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* D-Link */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table); ++ ++static int rtw_8821cu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return rtw_usb_probe(intf, id); ++} ++ ++static struct usb_driver rtw_8821cu_driver = { ++ .name = "rtw_8821cu", ++ .id_table = rtw_8821cu_id_table, ++ .probe = rtw_8821cu_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8821cu_driver); ++ ++MODULE_AUTHOR("Hans Ulli Kroll "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index dbfd67c3f598..3017a9760da8 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -15,6 +15,7 @@ + #include "reg.h" + #include "debug.h" + #include "bf.h" ++#include "regd.h" + + static void rtw8822b_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path); +@@ -25,6 +26,18 @@ static void rtw8822be_efuse_parsing(struct rtw_efuse *efuse, + ether_addr_copy(efuse->addr, map->e.mac_addr); + } + ++static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8822b_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->u.mac_addr); ++} ++ ++static void rtw8822bs_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8822b_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->s.mac_addr); ++} ++ + static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + { + struct rtw_efuse *efuse = &rtwdev->efuse; +@@ -55,6 +68,12 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + case RTW_HCI_TYPE_PCIE: + rtw8822be_efuse_parsing(efuse, map); + break; ++ case RTW_HCI_TYPE_USB: ++ rtw8822bu_efuse_parsing(efuse, map); ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rtw8822bs_efuse_parsing(efuse, map); ++ break; + default: + /* unsupported now */ + return -ENOTSUPP; +@@ -87,7 +106,7 @@ static const u32 rtw8822b_txscale_tbl[RTW_TXSCALE_SIZE] = { + 0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe + }; + +-static const u8 rtw8822b_get_swing_index(struct rtw_dev *rtwdev) ++static u8 rtw8822b_get_swing_index(struct rtw_dev *rtwdev) + { + u8 i = 0; + u32 swing, table_value; +@@ -261,6 +280,8 @@ static int rtw8822b_mac_init(struct rtw_dev *rtwdev) + rtw_write8(rtwdev, REG_TCR + 1, WLAN_TX_FUNC_CFG1); + rtw_write32(rtwdev, REG_WMAC_OPTION_FUNCTION + 8, WLAN_MAC_OPT_FUNC2); + rtw_write8(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, WLAN_MAC_OPT_NORM_FUNC1); ++ rtw_write8_set(rtwdev, REG_SND_PTCL_CTRL, ++ BIT_DIS_CHK_VHTSIGB_CRC); + + return 0; + } +@@ -1009,12 +1030,12 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev, + antenna_tx, antenna_rx); + + if (!rtw8822b_check_rf_path(antenna_tx)) { +- rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); ++ rtw_warn(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); + return -EINVAL; + } + + if (!rtw8822b_check_rf_path(antenna_rx)) { +- rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); ++ rtw_warn(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); + return -EINVAL; + } + +@@ -1120,21 +1141,21 @@ static void rtw8822b_coex_cfg_init(struct rtw_dev *rtwdev) + + /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ +- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); ++ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); +- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); ++ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); + /* wl tx signal to PTA not case EDCCA */ + rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN); + /* GNT_BT=1 while select both */ +- rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); ++ rtw_write16_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); + } + + static void rtw8822b_coex_cfg_ant_switch(struct rtw_dev *rtwdev, +@@ -1341,6 +1362,7 @@ static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) + coex_dm->cur_wl_rx_low_gain_en = low_gain; + + if (coex_dm->cur_wl_rx_low_gain_en) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table On!\n"); + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++) + rtw_write32(rtwdev, REG_RX_GAIN_EN, wl_rx_low_gain_on[i]); + +@@ -1350,6 +1372,7 @@ static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x1); + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x3f); + } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table Off!\n"); + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++) + rtw_write32(rtwdev, 0x81c, wl_rx_low_gain_off[i]); + +@@ -1434,7 +1457,7 @@ static void rtw8822b_pwrtrack_set(struct rtw_dev *rtwdev, u8 path) + u8 pwr_idx_offset, tx_pwr_idx; + u8 channel = rtwdev->hal.current_channel; + u8 band_width = rtwdev->hal.current_band_width; +- u8 regd = rtwdev->regd.txpwr_regd; ++ u8 regd = rtw_regd_get(rtwdev); + u8 tx_rate = dm_info->tx_rate; + u8 max_pwr_idx = rtwdev->chip->max_power_index; + +@@ -1550,6 +1573,48 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif, + rtw_warn(rtwdev, "wrong bfee role\n"); + } + ++static void rtw8822b_adaptivity_init(struct rtw_dev *rtwdev) ++{ ++ rtw_phy_set_edcca_th(rtwdev, RTW8822B_EDCCA_MAX, RTW8822B_EDCCA_MAX); ++ ++ /* mac edcca state setting */ ++ rtw_write32_clr(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA); ++ rtw_write32_set(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN); ++ rtw_write32_mask(rtwdev, REG_EDCCA_SOURCE, BIT_SOURCE_OPTION, ++ RTW8822B_EDCCA_SRC_DEF); ++ rtw_write32_mask(rtwdev, REG_EDCCA_POW_MA, BIT_MA_LEVEL, 0); ++ ++ /* edcca decision opt */ ++ rtw_write32_set(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION); ++} ++ ++static void rtw8822b_adaptivity(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ s8 l2h, h2l; ++ u8 igi; ++ ++ igi = dm_info->igi_history[0]; ++ if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) { ++ l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB); ++ h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL; ++ } else { ++ l2h = min_t(s8, igi, dm_info->l2h_th_ini); ++ h2l = l2h - EDCCA_L2H_H2L_DIFF; ++ } ++ ++ rtw_phy_set_edcca_th(rtwdev, l2h, h2l); ++} ++ ++static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */ ++ ++ fill_txdesc_checksum_common(txdesc, words); ++} ++ + static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, +@@ -2123,6 +2188,9 @@ static struct rtw_chip_ops rtw8822b_ops = { + .config_bfee = rtw8822b_bf_config_bfee, + .set_gid_table = rtw_bf_set_gid_table, + .cfg_csi_rate = rtw_bf_cfg_csi_rate, ++ .adaptivity_init = rtw8822b_adaptivity_init, ++ .adaptivity = rtw8822b_adaptivity, ++ .fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum, + + .coex_set_init = rtw8822b_coex_cfg_init, + .coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch, +@@ -2141,14 +2209,14 @@ static const struct coex_table_para table_sant_8822b[] = { + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ +- {0x6a5a6a5a, 0xaaaaaaaa}, ++ {0x6a5a5555, 0xaaaaaaaa}, + {0x6a5a56aa, 0x6a5a56aa}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-10 */ + {0x66555555, 0xfafafafa}, + {0x66555555, 0x5a5a5aaa}, +- {0x66555555, 0x5aaa5aaa}, ++ {0x66555555, 0x6aaa5aaa}, + {0x66555555, 0xaaaa5aaa}, + {0x66555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, +@@ -2158,13 +2226,16 @@ static const struct coex_table_para table_sant_8822b[] = { + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, +- {0xffffffff, 0x6a5a5a5a}, ++ {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x55555555}, + {0xffffffff, 0x6a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, + {0x55555555, 0x6a5a6a5a}, +- {0x66556655, 0x66556655} ++ {0x66556655, 0x66556655}, ++ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */ ++ {0xffffffff, 0x5aaa5aaa}, ++ {0x56555555, 0x5a5a5aaa}, + }; + + /* Non-Shared-Antenna Coex Table */ +@@ -2184,7 +2255,7 @@ static const struct coex_table_para table_nsant_8822b[] = { + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, +- {0xaaffffaa, 0xfafafafa}, /* case-115 */ ++ {0xffff55ff, 0xffff55ff}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, +@@ -2213,7 +2284,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = { + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ +- { {0x51, 0x45, 0x03, 0x10, 0x10} }, ++ { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, +@@ -2221,7 +2292,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = { + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, +- { {0x65, 0x10, 0x03, 0x11, 0x11} }, ++ { {0x65, 0x10, 0x03, 0x11, 0x10} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} }, + { {0x61, 0x08, 0x03, 0x11, 0x11} } +@@ -2230,7 +2301,7 @@ static const struct coex_tdma_para tdma_sant_8822b[] = { + /* Non-Shared-Antenna TDMA */ + static const struct coex_tdma_para tdma_nsant_8822b[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */ +- { {0x61, 0x45, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, +@@ -2249,13 +2320,13 @@ static const struct coex_tdma_para tdma_nsant_8822b[] = { + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, +- { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */ ++ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */ ++ { {0x51, 0x08, 0x03, 0x10, 0x50} } + }; + + /* rssi in percentage % (dbm = % - 100) */ + static const u8 wl_rssi_step_8822b[] = {60, 50, 44, 30}; + static const u8 bt_rssi_step_8822b[] = {30, 30, 30, 30}; +-static const struct coex_5g_afh_map afh_5g_8822b[] = { {0, 0, 0} }; + + /* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */ + static const struct coex_rf_para rf_para_tx_8822b[] = { +@@ -2276,6 +2347,27 @@ static const struct coex_rf_para rf_para_rx_8822b[] = { + {1, 13, true, 1} + }; + ++static const struct coex_5g_afh_map afh_5g_8822b[] = { ++ {120, 2, 4}, ++ {124, 8, 8}, ++ {128, 17, 8}, ++ {132, 26, 10}, ++ {136, 34, 8}, ++ {140, 42, 10}, ++ {144, 51, 8}, ++ {149, 62, 8}, ++ {153, 71, 10}, ++ {157, 77, 4}, ++ {118, 2, 4}, ++ {126, 12, 16}, ++ {134, 29, 16}, ++ {142, 46, 16}, ++ {151, 66, 16}, ++ {159, 76, 4}, ++ {122, 10, 20}, ++ {138, 37, 34}, ++ {155, 68, 20} ++}; + static_assert(ARRAY_SIZE(rf_para_tx_8822b) == ARRAY_SIZE(rf_para_rx_8822b)); + + static const u8 +@@ -2428,7 +2520,12 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { + {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + }; + +-struct rtw_chip_info rtw8822b_hw_spec = { ++static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { ++ [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0}, ++ [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0}, ++}; ++ ++const struct rtw_chip_info rtw8822b_hw_spec = { + .ops = &rtw8822b_ops, + .id = RTW_CHIP_TYPE_8822B, + .fw_name = "rtw88/rtw8822b_fw.bin", +@@ -2443,12 +2540,13 @@ struct rtw_chip_info rtw8822b_hw_spec = { + .txff_size = 262144, + .rxff_size = 24576, + .fw_rxff_size = 12288, ++ .rsvd_drv_pg_num = 8, + .txgi_factor = 1, + .is_pwr_by_rate_dec = true, + .max_power_index = 0x3f, + .csi_buf_pg_num = 0, + .band = RTW_BAND_2G | RTW_BAND_5G, +- .page_size = 128, ++ .page_size = TX_PAGE_SIZE, + .dig_min = 0x1c, + .ht_supported = true, + .vht_supported = true, +@@ -2476,11 +2574,18 @@ struct rtw_chip_info rtw8822b_hw_spec = { + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, + .rx_ldpc = true, ++ .edcca_th = rtw8822b_edcca_th, ++ .l2h_th_ini_cs = 10 + EDCCA_IGI_BASE, ++ .l2h_th_ini_ad = -14 + EDCCA_IGI_BASE, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2, ++ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, + + .coex_para_ver = 0x20070206, + .bt_desired_ver = 0x6, + .scbd_support = true, + .new_scbd10_def = false, ++ .ble_hid_profile_support = false, ++ .wl_mimo_ps_support = false, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_RATIO, + .ant_isolation = 15, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h +index 6211f4b547b9..2dc3a6660f06 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h +@@ -65,6 +65,11 @@ struct rtw8822be_efuse { + u8 res7; + }; + ++struct rtw8822bs_efuse { ++ u8 res4[0x4a]; /* 0xd0 */ ++ u8 mac_addr[ETH_ALEN]; /* 0x11a */ ++} __packed; ++ + struct rtw8822b_efuse { + __le16 rtl_id; + u8 res0[0x0e]; +@@ -92,8 +97,9 @@ struct rtw8822b_efuse { + u8 country_code[2]; + u8 res[3]; + union { +- struct rtw8822bu_efuse u; + struct rtw8822be_efuse e; ++ struct rtw8822bu_efuse u; ++ struct rtw8822bs_efuse s; + }; + }; + +@@ -140,6 +146,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8)) + ++#define RTW8822B_EDCCA_MAX 0x7f ++#define RTW8822B_EDCCA_SRC_DEF 1 + #define REG_HTSTFWT 0x800 + #define REG_RXPSEL 0x808 + #define BIT_RX_PSEL_RST (BIT(28) | BIT(29)) +@@ -152,11 +160,17 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_L1PKWT 0x840 + #define REG_MRC 0x850 + #define REG_CLKTRK 0x860 ++#define REG_EDCCA_POW_MA 0x8a0 ++#define BIT_MA_LEVEL GENMASK(1, 0) + #define REG_ADCCLK 0x8ac + #define REG_ADC160 0x8c4 + #define REG_ADC40 0x8c8 ++#define REG_EDCCA_DECISION 0x8dc ++#define BIT_EDCCA_OPTION BIT(5) + #define REG_CDDTXP 0x93c + #define REG_TXPSEL1 0x940 ++#define REG_EDCCA_SOURCE 0x944 ++#define BIT_SOURCE_OPTION GENMASK(29, 28) + #define REG_ACBB0 0x948 + #define REG_ACBBRXFIR 0x94c + #define REG_ACGG2TBL 0x958 +@@ -179,4 +193,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define REG_ANTWT 0x1904 + #define REG_IQKFAILMSK 0x1bf0 + ++extern const struct rtw_chip_info rtw8822b_hw_spec; ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.c b/drivers/net/wireless/realtek/rtw88/rtw8822be.c +index 921916ae15ca..4994950776cd 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822be.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822be.c +@@ -4,7 +4,8 @@ + + #include + #include +-#include "rtw8822be.h" ++#include "pci.h" ++#include "rtw8822b.h" + + static const struct pci_device_id rtw_8822be_id_table[] = { + { +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c +new file mode 100644 +index 000000000000..1ddef81dae0e +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) Jernej Skrabec ++ */ ++ ++#include ++#include "sdio_ids.h" ++#include ++#include "main.h" ++#include "rtw8822b.h" ++#include "sdio.h" ++ ++static const struct sdio_device_id rtw_8822bs_id_table[] = { ++ { ++ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, ++ SDIO_DEVICE_ID_REALTEK_RTW8822BS), ++ .driver_data = (kernel_ulong_t)&rtw8822b_hw_spec, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(sdio, rtw_8822bs_id_table); ++ ++static struct sdio_driver rtw_8822bs_driver = { ++ .name = "rtw_8822bs", ++ .probe = rtw_sdio_probe, ++ .remove = rtw_sdio_remove, ++ .id_table = rtw_8822bs_id_table, ++ .drv = { ++ .pm = &rtw_sdio_pm_ops, ++ .shutdown = rtw_sdio_shutdown, ++ } ++}; ++module_sdio_driver(rtw_8822bs_driver); ++ ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bs driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c +new file mode 100644 +index 000000000000..ab620a0b1dfc +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c +@@ -0,0 +1,90 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8822b.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8822bu_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2102, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* CCNC */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822ULC */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UTC */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xf822, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UAD */ ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb81a, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Default ID */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS AC1300 USB-AC55 B1 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x184c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS U2 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x19aa, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS - USB-AC58 rev A1 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1870, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1874, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-181 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-182 - D1 */ ++ {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331f, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec)}, /* Dlink - DWA-183 D Ver */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB6400M */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0045, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB3600 v2 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U v1 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U Plus v1 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T4U V3 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0116, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0117, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9055, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Netgear A6150 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0025, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Hawking HW12ACU */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x04ca, 0x8602, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */ ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table); ++ ++static int rtw8822bu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return rtw_usb_probe(intf, id); ++} ++ ++static struct usb_driver rtw_8822bu_driver = { ++ .name = "rtw_8822bu", ++ .id_table = rtw_8822bu_id_table, ++ .probe = rtw8822bu_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8822bu_driver); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bu driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index cee586335552..8078127a5e53 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -18,6 +18,8 @@ + #include "bf.h" + #include "efuse.h" + ++#define IQK_DONE_8822C 0xaa ++ + static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path); + +@@ -27,6 +29,18 @@ static void rtw8822ce_efuse_parsing(struct rtw_efuse *efuse, + ether_addr_copy(efuse->addr, map->e.mac_addr); + } + ++static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8822c_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->u.mac_addr); ++} ++ ++static void rtw8822cs_efuse_parsing(struct rtw_efuse *efuse, ++ struct rtw8822c_efuse *map) ++{ ++ ether_addr_copy(efuse->addr, map->s.mac_addr); ++} ++ + static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + { + struct rtw_efuse *efuse = &rtwdev->efuse; +@@ -37,7 +51,7 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + + efuse->rfe_option = map->rfe_option; + efuse->rf_board_option = map->rf_board_option; +- efuse->crystal_cap = map->xtal_k; ++ efuse->crystal_cap = map->xtal_k & XCAP_MASK; + efuse->channel_plan = map->channel_plan; + efuse->country_code[0] = map->country_code[0]; + efuse->country_code[1] = map->country_code[1]; +@@ -56,6 +70,12 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + case RTW_HCI_TYPE_PCIE: + rtw8822ce_efuse_parsing(efuse, map); + break; ++ case RTW_HCI_TYPE_USB: ++ rtw8822cu_efuse_parsing(efuse, map); ++ break; ++ case RTW_HCI_TYPE_SDIO: ++ rtw8822cs_efuse_parsing(efuse, map); ++ break; + default: + /* unsupported now */ + return -ENOTSUPP; +@@ -77,6 +97,13 @@ static void rtw8822c_header_file_init(struct rtw_dev *rtwdev, bool pre) + rtw_write32_set(rtwdev, REG_ENCCK, BIT_CCK_OFDM_BLK_EN); + } + ++static void rtw8822c_bb_reset(struct rtw_dev *rtwdev) ++{ ++ rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB); ++ rtw_write16_clr(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB); ++ rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB); ++} ++ + static void rtw8822c_dac_backup_reg(struct rtw_dev *rtwdev, + struct rtw_backup_info *backup, + struct rtw_backup_info *backup_rf) +@@ -1092,16 +1119,721 @@ static void rtw8822c_pa_bias(struct rtw_dev *rtwdev) + if (pg_pa_bias == EFUSE_READ_FAIL) + return; + pg_pa_bias = FIELD_GET(PPG_PABIAS_MASK, pg_pa_bias); +- rtw_write_rf(rtwdev, path, 0x60, RF_PABIAS_2G_MASK, pg_pa_bias); ++ rtw_write_rf(rtwdev, path, RF_PA, RF_PABIAS_2G_MASK, pg_pa_bias); + } + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { + rtw_read8_physical_efuse(rtwdev, rf_efuse_5g[path], + &pg_pa_bias); + pg_pa_bias = FIELD_GET(PPG_PABIAS_MASK, pg_pa_bias); +- rtw_write_rf(rtwdev, path, 0x60, RF_PABIAS_5G_MASK, pg_pa_bias); ++ rtw_write_rf(rtwdev, path, RF_PA, RF_PABIAS_5G_MASK, pg_pa_bias); ++ } ++} ++ ++static void rtw8822c_rfk_handshake(struct rtw_dev *rtwdev, bool is_before_k) ++{ ++ struct rtw_dm_info *dm = &rtwdev->dm_info; ++ u8 u1b_tmp; ++ u8 u4b_tmp; ++ int ret; ++ ++ if (is_before_k) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[RFK] WiFi / BT RFK handshake start!!\n"); ++ ++ if (!dm->is_bt_iqk_timeout) { ++ ret = read_poll_timeout(rtw_read32_mask, u4b_tmp, ++ u4b_tmp == 0, 20, 600000, false, ++ rtwdev, REG_PMC_DBG_CTRL1, ++ BITS_PMC_BT_IQK_STS); ++ if (ret) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[RFK] Wait BT IQK finish timeout!!\n"); ++ dm->is_bt_iqk_timeout = true; ++ } ++ } ++ ++ rtw_fw_inform_rfk_status(rtwdev, true); ++ ++ ret = read_poll_timeout(rtw_read8_mask, u1b_tmp, ++ u1b_tmp == 1, 20, 100000, false, ++ rtwdev, REG_ARFR4, BIT_WL_RFK); ++ if (ret) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[RFK] Send WiFi RFK start H2C cmd FAIL!!\n"); ++ } else { ++ rtw_fw_inform_rfk_status(rtwdev, false); ++ ret = read_poll_timeout(rtw_read8_mask, u1b_tmp, ++ u1b_tmp == 1, 20, 100000, false, ++ rtwdev, REG_ARFR4, ++ BIT_WL_RFK); ++ if (ret) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[RFK] Send WiFi RFK finish H2C cmd FAIL!!\n"); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[RFK] WiFi / BT RFK handshake finish!!\n"); ++ } ++} ++ ++static void rtw8822c_rfk_power_save(struct rtw_dev *rtwdev, ++ bool is_power_save) ++{ ++ u8 path; ++ ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ rtw_write32_mask(rtwdev, REG_DPD_CTL1_S0, BIT_PS_EN, ++ is_power_save ? 0 : 1); ++ } ++} ++ ++static void rtw8822c_txgapk_backup_bb_reg(struct rtw_dev *rtwdev, const u32 reg[], ++ u32 reg_backup[], u32 reg_num) ++{ ++ u32 i; ++ ++ for (i = 0; i < reg_num; i++) { ++ reg_backup[i] = rtw_read32(rtwdev, reg[i]); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] Backup BB 0x%x = 0x%x\n", ++ reg[i], reg_backup[i]); ++ } ++} ++ ++static void rtw8822c_txgapk_reload_bb_reg(struct rtw_dev *rtwdev, ++ const u32 reg[], u32 reg_backup[], ++ u32 reg_num) ++{ ++ u32 i; ++ ++ for (i = 0; i < reg_num; i++) { ++ rtw_write32(rtwdev, reg[i], reg_backup[i]); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] Reload BB 0x%x = 0x%x\n", ++ reg[i], reg_backup[i]); ++ } ++} ++ ++static bool check_rf_status(struct rtw_dev *rtwdev, u8 status) ++{ ++ u8 reg_rf0_a, reg_rf0_b; ++ ++ reg_rf0_a = (u8)rtw_read_rf(rtwdev, RF_PATH_A, ++ RF_MODE_TRXAGC, BIT_RF_MODE); ++ reg_rf0_b = (u8)rtw_read_rf(rtwdev, RF_PATH_B, ++ RF_MODE_TRXAGC, BIT_RF_MODE); ++ ++ if (reg_rf0_a == status || reg_rf0_b == status) ++ return false; ++ ++ return true; ++} ++ ++static void rtw8822c_txgapk_tx_pause(struct rtw_dev *rtwdev) ++{ ++ bool status; ++ int ret; ++ ++ rtw_write8(rtwdev, REG_TXPAUSE, BIT_AC_QUEUE); ++ rtw_write32_mask(rtwdev, REG_TX_FIFO, BIT_STOP_TX, 0x2); ++ ++ ret = read_poll_timeout_atomic(check_rf_status, status, status, ++ 2, 5000, false, rtwdev, 2); ++ if (ret) ++ rtw_warn(rtwdev, "failed to pause TX\n"); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] Tx pause!!\n"); ++} ++ ++static void rtw8822c_txgapk_bb_dpk(struct rtw_dev *rtwdev, u8 path) ++{ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ rtw_write32_mask(rtwdev, REG_ENFN, BIT_IQK_DPK_EN, 0x1); ++ rtw_write32_mask(rtwdev, REG_CH_DELAY_EXTR2, ++ BIT_IQK_DPK_CLOCK_SRC, 0x1); ++ rtw_write32_mask(rtwdev, REG_CH_DELAY_EXTR2, ++ BIT_IQK_DPK_RESET_SRC, 0x1); ++ rtw_write32_mask(rtwdev, REG_CH_DELAY_EXTR2, BIT_EN_IOQ_IQK_DPK, 0x1); ++ rtw_write32_mask(rtwdev, REG_CH_DELAY_EXTR2, BIT_TST_IQK2SET_SRC, 0x0); ++ rtw_write32_mask(rtwdev, REG_CCA_OFF, BIT_CCA_ON_BY_PW, 0x1ff); ++ ++ if (path == RF_PATH_A) { ++ rtw_write32_mask(rtwdev, REG_RFTXEN_GCK_A, ++ BIT_RFTXEN_GCK_FORCE_ON, 0x1); ++ rtw_write32_mask(rtwdev, REG_3WIRE, BIT_DIS_SHARERX_TXGAT, 0x1); ++ rtw_write32_mask(rtwdev, REG_DIS_SHARE_RX_A, ++ BIT_TX_SCALE_0DB, 0x1); ++ rtw_write32_mask(rtwdev, REG_3WIRE, BIT_3WIRE_EN, 0x0); ++ } else if (path == RF_PATH_B) { ++ rtw_write32_mask(rtwdev, REG_RFTXEN_GCK_B, ++ BIT_RFTXEN_GCK_FORCE_ON, 0x1); ++ rtw_write32_mask(rtwdev, REG_3WIRE2, ++ BIT_DIS_SHARERX_TXGAT, 0x1); ++ rtw_write32_mask(rtwdev, REG_DIS_SHARE_RX_B, ++ BIT_TX_SCALE_0DB, 0x1); ++ rtw_write32_mask(rtwdev, REG_3WIRE2, BIT_3WIRE_EN, 0x0); ++ } ++ rtw_write32_mask(rtwdev, REG_CCKSB, BIT_BBMODE, 0x2); ++} ++ ++static void rtw8822c_txgapk_afe_dpk(struct rtw_dev *rtwdev, u8 path) ++{ ++ u32 reg; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (path == RF_PATH_A) { ++ reg = REG_ANAPAR_A; ++ } else if (path == RF_PATH_B) { ++ reg = REG_ANAPAR_B; ++ } else { ++ rtw_err(rtwdev, "[TXGAPK] unknown path %d!!\n", path); ++ return; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_IQK_CTRL, MASKDWORD, MASKDWORD); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x700f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x700f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x701f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x702f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x703f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x704f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x705f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x706f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x707f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x708f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x709f0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70af0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70bf0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70cf0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70df0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70ef0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70ff0001); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70ff0001); ++} ++ ++static void rtw8822c_txgapk_afe_dpk_restore(struct rtw_dev *rtwdev, u8 path) ++{ ++ u32 reg; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (path == RF_PATH_A) { ++ reg = REG_ANAPAR_A; ++ } else if (path == RF_PATH_B) { ++ reg = REG_ANAPAR_B; ++ } else { ++ rtw_err(rtwdev, "[TXGAPK] unknown path %d!!\n", path); ++ return; ++ } ++ rtw_write32_mask(rtwdev, REG_IQK_CTRL, MASKDWORD, 0xffa1005e); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x700b8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70144041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70244041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70344041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70444041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x705b8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70644041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x707b8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x708b8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x709b8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70ab8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70bb8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70cb8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70db8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70eb8041); ++ rtw_write32_mask(rtwdev, reg, MASKDWORD, 0x70fb8041); ++} ++ ++static void rtw8822c_txgapk_bb_dpk_restore(struct rtw_dev *rtwdev, u8 path) ++{ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TX_GAIN, 0x0); ++ rtw_write_rf(rtwdev, path, RF_DIS_BYPASS_TXBB, BIT_TIA_BYPASS, 0x0); ++ rtw_write_rf(rtwdev, path, RF_DIS_BYPASS_TXBB, BIT_TXBB, 0x0); ++ ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, 0x0); ++ rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_TX_CFIR, 0x0); ++ rtw_write32_mask(rtwdev, REG_SINGLE_TONE_SW, BIT_IRQ_TEST_MODE, 0x0); ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, MASKBYTE0, 0x00); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, 0x1); ++ rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_TX_CFIR, 0x0); ++ rtw_write32_mask(rtwdev, REG_SINGLE_TONE_SW, BIT_IRQ_TEST_MODE, 0x0); ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, MASKBYTE0, 0x00); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, 0x0); ++ rtw_write32_mask(rtwdev, REG_CCA_OFF, BIT_CCA_ON_BY_PW, 0x0); ++ ++ if (path == RF_PATH_A) { ++ rtw_write32_mask(rtwdev, REG_RFTXEN_GCK_A, ++ BIT_RFTXEN_GCK_FORCE_ON, 0x0); ++ rtw_write32_mask(rtwdev, REG_3WIRE, BIT_DIS_SHARERX_TXGAT, 0x0); ++ rtw_write32_mask(rtwdev, REG_DIS_SHARE_RX_A, ++ BIT_TX_SCALE_0DB, 0x0); ++ rtw_write32_mask(rtwdev, REG_3WIRE, BIT_3WIRE_EN, 0x3); ++ } else if (path == RF_PATH_B) { ++ rtw_write32_mask(rtwdev, REG_RFTXEN_GCK_B, ++ BIT_RFTXEN_GCK_FORCE_ON, 0x0); ++ rtw_write32_mask(rtwdev, REG_3WIRE2, ++ BIT_DIS_SHARERX_TXGAT, 0x0); ++ rtw_write32_mask(rtwdev, REG_DIS_SHARE_RX_B, ++ BIT_TX_SCALE_0DB, 0x0); ++ rtw_write32_mask(rtwdev, REG_3WIRE2, BIT_3WIRE_EN, 0x3); ++ } ++ ++ rtw_write32_mask(rtwdev, REG_CCKSB, BIT_BBMODE, 0x0); ++ rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_CFIR_EN, 0x5); ++} ++ ++static bool _rtw8822c_txgapk_gain_valid(struct rtw_dev *rtwdev, u32 gain) ++{ ++ if ((FIELD_GET(BIT_GAIN_TX_PAD_H, gain) >= 0xc) && ++ (FIELD_GET(BIT_GAIN_TX_PAD_L, gain) >= 0xe)) ++ return true; ++ ++ return false; ++} ++ ++static void _rtw8822c_txgapk_write_gain_bb_table(struct rtw_dev *rtwdev, ++ u8 band, u8 path) ++{ ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ u32 v, tmp_3f = 0; ++ u8 gain, check_txgain; ++ ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ ++ switch (band) { ++ case RF_BAND_2G_OFDM: ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x0); ++ break; ++ case RF_BAND_5G_L: ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x2); ++ break; ++ case RF_BAND_5G_M: ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x3); ++ break; ++ case RF_BAND_5G_H: ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x4); ++ break; ++ default: ++ break; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_TX_GAIN_SET, MASKBYTE0, 0x88); ++ ++ check_txgain = 0; ++ for (gain = 0; gain < RF_GAIN_NUM; gain++) { ++ v = txgapk->rf3f_bp[band][gain][path]; ++ if (_rtw8822c_txgapk_gain_valid(rtwdev, v)) { ++ if (!check_txgain) { ++ tmp_3f = txgapk->rf3f_bp[band][gain][path]; ++ check_txgain = 1; ++ } ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] tx_gain=0x%03X >= 0xCEX\n", ++ txgapk->rf3f_bp[band][gain][path]); ++ } else { ++ tmp_3f = txgapk->rf3f_bp[band][gain][path]; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN, tmp_3f); ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_I_GAIN, gain); ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_GAIN_RST, 0x1); ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_GAIN_RST, 0x0); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] Band=%d 0x1b98[11:0]=0x%03X path=%d\n", ++ band, tmp_3f, path); + } + } + ++static void rtw8822c_txgapk_write_gain_bb_table(struct rtw_dev *rtwdev) ++{ ++ u8 path, band; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s channel=%d\n", ++ __func__, rtwdev->dm_info.gapk.channel); ++ ++ for (band = 0; band < RF_BAND_MAX; band++) { ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ _rtw8822c_txgapk_write_gain_bb_table(rtwdev, ++ band, path); ++ } ++ } ++} ++ ++static void rtw8822c_txgapk_read_offset(struct rtw_dev *rtwdev, u8 path) ++{ ++ static const u32 cfg1_1b00[2] = {0x00000d18, 0x00000d2a}; ++ static const u32 cfg2_1b00[2] = {0x00000d19, 0x00000d2b}; ++ static const u32 set_pi[2] = {REG_RSV_CTRL, REG_WLRF1}; ++ static const u32 path_setting[2] = {REG_ORITXCODE, REG_ORITXCODE2}; ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ u8 channel = txgapk->channel; ++ u32 val; ++ int i; ++ ++ if (path >= ARRAY_SIZE(cfg1_1b00) || ++ path >= ARRAY_SIZE(cfg2_1b00) || ++ path >= ARRAY_SIZE(set_pi) || ++ path >= ARRAY_SIZE(path_setting)) { ++ rtw_warn(rtwdev, "[TXGAPK] wrong path %d\n", path); ++ return; ++ } ++ ++ rtw_write32_mask(rtwdev, REG_ANTMAP0, BIT_ANT_PATH, path + 1); ++ rtw_write32_mask(rtwdev, REG_TXLGMAP, MASKDWORD, 0xe4e40000); ++ rtw_write32_mask(rtwdev, REG_TXANTSEG, BIT_ANTSEG, 0x3); ++ rtw_write32_mask(rtwdev, path_setting[path], MASK20BITS, 0x33312); ++ rtw_write32_mask(rtwdev, path_setting[path], BIT_PATH_EN, 0x1); ++ rtw_write32_mask(rtwdev, set_pi[path], BITS_RFC_DIRECT, 0x0); ++ rtw_write_rf(rtwdev, path, RF_LUTDBG, BIT_TXA_TANK, 0x1); ++ rtw_write_rf(rtwdev, path, RF_IDAC, BIT_TX_MODE, 0x820); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ rtw_write32_mask(rtwdev, REG_IQKSTAT, MASKBYTE0, 0x0); ++ ++ rtw_write32_mask(rtwdev, REG_TX_TONE_IDX, MASKBYTE0, 0x018); ++ fsleep(1000); ++ if (channel >= 1 && channel <= 14) ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, MASKBYTE0, BIT_2G_SWING); ++ else ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, MASKBYTE0, BIT_5G_SWING); ++ fsleep(1000); ++ ++ rtw_write32_mask(rtwdev, REG_NCTL0, MASKDWORD, cfg1_1b00[path]); ++ rtw_write32_mask(rtwdev, REG_NCTL0, MASKDWORD, cfg2_1b00[path]); ++ ++ read_poll_timeout(rtw_read32_mask, val, ++ val == 0x55, 1000, 100000, false, ++ rtwdev, REG_RPT_CIP, BIT_RPT_CIP_STATUS); ++ ++ rtw_write32_mask(rtwdev, set_pi[path], BITS_RFC_DIRECT, 0x2); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ rtw_write32_mask(rtwdev, REG_RXSRAM_CTL, BIT_RPT_EN, 0x1); ++ rtw_write32_mask(rtwdev, REG_RXSRAM_CTL, BIT_RPT_SEL, 0x12); ++ rtw_write32_mask(rtwdev, REG_TX_GAIN_SET, BIT_GAPK_RPT_IDX, 0x3); ++ val = rtw_read32(rtwdev, REG_STAT_RPT); ++ ++ txgapk->offset[0][path] = (s8)FIELD_GET(BIT_GAPK_RPT0, val); ++ txgapk->offset[1][path] = (s8)FIELD_GET(BIT_GAPK_RPT1, val); ++ txgapk->offset[2][path] = (s8)FIELD_GET(BIT_GAPK_RPT2, val); ++ txgapk->offset[3][path] = (s8)FIELD_GET(BIT_GAPK_RPT3, val); ++ txgapk->offset[4][path] = (s8)FIELD_GET(BIT_GAPK_RPT4, val); ++ txgapk->offset[5][path] = (s8)FIELD_GET(BIT_GAPK_RPT5, val); ++ txgapk->offset[6][path] = (s8)FIELD_GET(BIT_GAPK_RPT6, val); ++ txgapk->offset[7][path] = (s8)FIELD_GET(BIT_GAPK_RPT7, val); ++ ++ rtw_write32_mask(rtwdev, REG_TX_GAIN_SET, BIT_GAPK_RPT_IDX, 0x4); ++ val = rtw_read32(rtwdev, REG_STAT_RPT); ++ ++ txgapk->offset[8][path] = (s8)FIELD_GET(BIT_GAPK_RPT0, val); ++ txgapk->offset[9][path] = (s8)FIELD_GET(BIT_GAPK_RPT1, val); ++ ++ for (i = 0; i < RF_HW_OFFSET_NUM; i++) ++ if (txgapk->offset[i][path] & BIT(3)) ++ txgapk->offset[i][path] = txgapk->offset[i][path] | ++ 0xf0; ++ for (i = 0; i < RF_HW_OFFSET_NUM; i++) ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] offset %d %d path=%d\n", ++ txgapk->offset[i][path], i, path); ++} ++ ++static void rtw8822c_txgapk_calculate_offset(struct rtw_dev *rtwdev, u8 path) ++{ ++ static const u32 bb_reg[] = {REG_ANTMAP0, REG_TXLGMAP, REG_TXANTSEG, ++ REG_ORITXCODE, REG_ORITXCODE2}; ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ u8 channel = txgapk->channel; ++ u32 reg_backup[ARRAY_SIZE(bb_reg)] = {0}; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s channel=%d\n", ++ __func__, channel); ++ ++ rtw8822c_txgapk_backup_bb_reg(rtwdev, bb_reg, ++ reg_backup, ARRAY_SIZE(bb_reg)); ++ ++ if (channel >= 1 && channel <= 14) { ++ rtw_write32_mask(rtwdev, ++ REG_SINGLE_TONE_SW, BIT_IRQ_TEST_MODE, 0x0); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, BIT_IQ_SWITCH, 0x3f); ++ rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_TX_CFIR, 0x0); ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TX_GAIN, 0x1); ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, RFREG_MASK, 0x5000f); ++ rtw_write_rf(rtwdev, path, RF_TX_GAIN_OFFSET, BIT_RF_GAIN, 0x0); ++ rtw_write_rf(rtwdev, path, RF_RXG_GAIN, BIT_RXG_GAIN, 0x1); ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, BIT_RXAGC, 0x0f); ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TRXBW, 0x1); ++ rtw_write_rf(rtwdev, path, RF_BW_TRXBB, BIT_BW_TXBB, 0x1); ++ rtw_write_rf(rtwdev, path, RF_BW_TRXBB, BIT_BW_RXBB, 0x0); ++ rtw_write_rf(rtwdev, path, RF_EXT_TIA_BW, BIT_PW_EXT_TIA, 0x1); ++ ++ rtw_write32_mask(rtwdev, REG_IQKSTAT, MASKBYTE0, 0x00); ++ rtw_write32_mask(rtwdev, REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x0); ++ ++ rtw8822c_txgapk_read_offset(rtwdev, path); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "=============================\n"); ++ ++ } else { ++ rtw_write32_mask(rtwdev, ++ REG_SINGLE_TONE_SW, BIT_IRQ_TEST_MODE, 0x0); ++ rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SEL_PATH, path); ++ rtw_write32_mask(rtwdev, REG_R_CONFIG, BIT_IQ_SWITCH, 0x3f); ++ rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_TX_CFIR, 0x0); ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TX_GAIN, 0x1); ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, RFREG_MASK, 0x50011); ++ rtw_write_rf(rtwdev, path, RF_TXA_LB_SW, BIT_TXA_LB_ATT, 0x3); ++ rtw_write_rf(rtwdev, path, RF_TXA_LB_SW, BIT_LB_ATT, 0x3); ++ rtw_write_rf(rtwdev, path, RF_TXA_LB_SW, BIT_LB_SW, 0x1); ++ rtw_write_rf(rtwdev, path, ++ RF_RXA_MIX_GAIN, BIT_RXA_MIX_GAIN, 0x2); ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, BIT_RXAGC, 0x12); ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TRXBW, 0x1); ++ rtw_write_rf(rtwdev, path, RF_BW_TRXBB, BIT_BW_RXBB, 0x0); ++ rtw_write_rf(rtwdev, path, RF_EXT_TIA_BW, BIT_PW_EXT_TIA, 0x1); ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, BIT_RF_MODE, 0x5); ++ ++ rtw_write32_mask(rtwdev, REG_IQKSTAT, MASKBYTE0, 0x0); ++ ++ if (channel >= 36 && channel <= 64) ++ rtw_write32_mask(rtwdev, ++ REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x2); ++ else if (channel >= 100 && channel <= 144) ++ rtw_write32_mask(rtwdev, ++ REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x3); ++ else if (channel >= 149 && channel <= 177) ++ rtw_write32_mask(rtwdev, ++ REG_TABLE_SEL, BIT_Q_GAIN_SEL, 0x4); ++ ++ rtw8822c_txgapk_read_offset(rtwdev, path); ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "=============================\n"); ++ } ++ rtw8822c_txgapk_reload_bb_reg(rtwdev, bb_reg, ++ reg_backup, ARRAY_SIZE(bb_reg)); ++} ++ ++static void rtw8822c_txgapk_rf_restore(struct rtw_dev *rtwdev, u8 path) ++{ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (path >= rtwdev->hal.rf_path_num) ++ return; ++ ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, BIT_RF_MODE, 0x3); ++ rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TRXBW, 0x0); ++ rtw_write_rf(rtwdev, path, RF_EXT_TIA_BW, BIT_PW_EXT_TIA, 0x0); ++} ++ ++static u32 rtw8822c_txgapk_cal_gain(struct rtw_dev *rtwdev, u32 gain, s8 offset) ++{ ++ u32 gain_x2, new_gain; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (_rtw8822c_txgapk_gain_valid(rtwdev, gain)) { ++ new_gain = gain; ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] gain=0x%03X(>=0xCEX) offset=%d new_gain=0x%03X\n", ++ gain, offset, new_gain); ++ return new_gain; ++ } ++ ++ gain_x2 = (gain << 1) + offset; ++ new_gain = (gain_x2 >> 1) | (gain_x2 & BIT(0) ? BIT_GAIN_EXT : 0); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] gain=0x%X offset=%d new_gain=0x%X\n", ++ gain, offset, new_gain); ++ ++ return new_gain; ++} ++ ++static void rtw8822c_txgapk_write_tx_gain(struct rtw_dev *rtwdev) ++{ ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ u32 i, j, tmp = 0x20, tmp_3f, v; ++ s8 offset_tmp[RF_GAIN_NUM] = {0}; ++ u8 path, band = RF_BAND_2G_OFDM, channel = txgapk->channel; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (channel >= 1 && channel <= 14) { ++ tmp = 0x20; ++ band = RF_BAND_2G_OFDM; ++ } else if (channel >= 36 && channel <= 64) { ++ tmp = 0x200; ++ band = RF_BAND_5G_L; ++ } else if (channel >= 100 && channel <= 144) { ++ tmp = 0x280; ++ band = RF_BAND_5G_M; ++ } else if (channel >= 149 && channel <= 177) { ++ tmp = 0x300; ++ band = RF_BAND_5G_H; ++ } else { ++ rtw_err(rtwdev, "[TXGAPK] unknown channel %d!!\n", channel); ++ return; ++ } ++ ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ for (i = 0; i < RF_GAIN_NUM; i++) { ++ offset_tmp[i] = 0; ++ for (j = i; j < RF_GAIN_NUM; j++) { ++ v = txgapk->rf3f_bp[band][j][path]; ++ if (_rtw8822c_txgapk_gain_valid(rtwdev, v)) ++ continue; ++ ++ offset_tmp[i] += txgapk->offset[j][path]; ++ txgapk->fianl_offset[i][path] = offset_tmp[i]; ++ } ++ ++ v = txgapk->rf3f_bp[band][i][path]; ++ if (_rtw8822c_txgapk_gain_valid(rtwdev, v)) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] tx_gain=0x%03X >= 0xCEX\n", ++ txgapk->rf3f_bp[band][i][path]); ++ } else { ++ txgapk->rf3f_fs[path][i] = offset_tmp[i]; ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] offset %d %d\n", ++ offset_tmp[i], i); ++ } ++ } ++ ++ rtw_write_rf(rtwdev, path, RF_LUTWE2, RFREG_MASK, 0x10000); ++ for (i = 0; i < RF_GAIN_NUM; i++) { ++ rtw_write_rf(rtwdev, path, ++ RF_LUTWA, RFREG_MASK, tmp + i); ++ ++ tmp_3f = rtw8822c_txgapk_cal_gain(rtwdev, ++ txgapk->rf3f_bp[band][i][path], ++ offset_tmp[i]); ++ rtw_write_rf(rtwdev, path, RF_LUTWD0, ++ BIT_GAIN_EXT | BIT_DATA_L, tmp_3f); ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] 0x33=0x%05X 0x3f=0x%04X\n", ++ tmp + i, tmp_3f); ++ } ++ rtw_write_rf(rtwdev, path, RF_LUTWE2, RFREG_MASK, 0x0); ++ } ++} ++ ++static void rtw8822c_txgapk_save_all_tx_gain_table(struct rtw_dev *rtwdev) ++{ ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ static const u32 three_wire[2] = {REG_3WIRE, REG_3WIRE2}; ++ static const u8 ch_num[RF_BAND_MAX] = {1, 1, 36, 100, 149}; ++ static const u8 band_num[RF_BAND_MAX] = {0x0, 0x0, 0x1, 0x3, 0x5}; ++ static const u8 cck[RF_BAND_MAX] = {0x1, 0x0, 0x0, 0x0, 0x0}; ++ u8 path, band, gain, rf0_idx; ++ u32 rf18, v; ++ ++ if (rtwdev->dm_info.dm_flags & BIT(RTW_DM_CAP_TXGAPK)) ++ return; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ if (txgapk->read_txgain == 1) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] Already Read txgapk->read_txgain return!!!\n"); ++ rtw8822c_txgapk_write_gain_bb_table(rtwdev); ++ return; ++ } ++ ++ for (band = 0; band < RF_BAND_MAX; band++) { ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ rf18 = rtw_read_rf(rtwdev, path, RF_CFGCH, RFREG_MASK); ++ ++ rtw_write32_mask(rtwdev, ++ three_wire[path], BIT_3WIRE_EN, 0x0); ++ rtw_write_rf(rtwdev, path, ++ RF_CFGCH, MASKBYTE0, ch_num[band]); ++ rtw_write_rf(rtwdev, path, ++ RF_CFGCH, BIT_BAND, band_num[band]); ++ rtw_write_rf(rtwdev, path, ++ RF_BW_TRXBB, BIT_DBG_CCK_CCA, cck[band]); ++ rtw_write_rf(rtwdev, path, ++ RF_BW_TRXBB, BIT_TX_CCK_IND, cck[band]); ++ gain = 0; ++ for (rf0_idx = 1; rf0_idx < 32; rf0_idx += 3) { ++ rtw_write_rf(rtwdev, path, RF_MODE_TRXAGC, ++ MASKBYTE0, rf0_idx); ++ v = rtw_read_rf(rtwdev, path, ++ RF_TX_RESULT, RFREG_MASK); ++ txgapk->rf3f_bp[band][gain][path] = v & BIT_DATA_L; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] 0x5f=0x%03X band=%d path=%d\n", ++ txgapk->rf3f_bp[band][gain][path], ++ band, path); ++ gain++; ++ } ++ rtw_write_rf(rtwdev, path, RF_CFGCH, RFREG_MASK, rf18); ++ rtw_write32_mask(rtwdev, ++ three_wire[path], BIT_3WIRE_EN, 0x3); ++ } ++ } ++ rtw8822c_txgapk_write_gain_bb_table(rtwdev); ++ txgapk->read_txgain = 1; ++} ++ ++static void rtw8822c_txgapk(struct rtw_dev *rtwdev) ++{ ++ static const u32 bb_reg[2] = {REG_TX_PTCL_CTRL, REG_TX_FIFO}; ++ struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; ++ u32 bb_reg_backup[2]; ++ u8 path; ++ ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] ======>%s\n", __func__); ++ ++ rtw8822c_txgapk_save_all_tx_gain_table(rtwdev); ++ ++ if (txgapk->read_txgain == 0) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] txgapk->read_txgain == 0 return!!!\n"); ++ return; ++ } ++ ++ if (rtwdev->efuse.power_track_type >= 4 && ++ rtwdev->efuse.power_track_type <= 7) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, ++ "[TXGAPK] Normal Mode in TSSI mode. return!!!\n"); ++ return; ++ } ++ ++ rtw8822c_txgapk_backup_bb_reg(rtwdev, bb_reg, ++ bb_reg_backup, ARRAY_SIZE(bb_reg)); ++ rtw8822c_txgapk_tx_pause(rtwdev); ++ for (path = 0; path < rtwdev->hal.rf_path_num; path++) { ++ txgapk->channel = rtw_read_rf(rtwdev, path, ++ RF_CFGCH, RFREG_MASK) & MASKBYTE0; ++ rtw8822c_txgapk_bb_dpk(rtwdev, path); ++ rtw8822c_txgapk_afe_dpk(rtwdev, path); ++ rtw8822c_txgapk_calculate_offset(rtwdev, path); ++ rtw8822c_txgapk_rf_restore(rtwdev, path); ++ rtw8822c_txgapk_afe_dpk_restore(rtwdev, path); ++ rtw8822c_txgapk_bb_dpk_restore(rtwdev, path); ++ } ++ rtw8822c_txgapk_write_tx_gain(rtwdev); ++ rtw8822c_txgapk_reload_bb_reg(rtwdev, bb_reg, ++ bb_reg_backup, ARRAY_SIZE(bb_reg)); ++} ++ ++static void rtw8822c_do_gapk(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm = &rtwdev->dm_info; ++ ++ if (dm->dm_flags & BIT(RTW_DM_CAP_TXGAPK)) { ++ rtw_dbg(rtwdev, RTW_DBG_RFK, "[TXGAPK] feature disable!!!\n"); ++ return; ++ } ++ rtw8822c_rfk_handshake(rtwdev, true); ++ rtw8822c_txgapk(rtwdev); ++ rtw8822c_rfk_handshake(rtwdev, false); ++} ++ + static void rtw8822c_rf_init(struct rtw_dev *rtwdev) + { + rtw8822c_rf_dac_cal(rtwdev); +@@ -1388,6 +2120,8 @@ static int rtw8822c_mac_init(struct rtw_dev *rtwdev) + BIT_RXPSF_CONT_ERRCHKEN); + value16 = BIT_SET_RXPSF_ERRTHR(value16, 0x07); + rtw_write16(rtwdev, REG_RXPSF_CTRL, value16); ++ rtw_write8_set(rtwdev, REG_SND_PTCL_CTRL, ++ BIT_DIS_CHK_VHTSIGB_CRC); + + /* Interrupt migration configuration */ + rtw_write32(rtwdev, REG_INT_MIG, WLAN_MAC_INT_MIG_CFG); +@@ -1395,6 +2129,53 @@ static int rtw8822c_mac_init(struct rtw_dev *rtwdev) + return 0; + } + ++#define FWCD_SIZE_REG_8822C 0x2000 ++#define FWCD_SIZE_DMEM_8822C 0x10000 ++#define FWCD_SIZE_IMEM_8822C 0x10000 ++#define FWCD_SIZE_EMEM_8822C 0x20000 ++#define FWCD_SIZE_ROM_8822C 0x10000 ++ ++static const u32 __fwcd_segs_8822c[] = { ++ FWCD_SIZE_REG_8822C, ++ FWCD_SIZE_DMEM_8822C, ++ FWCD_SIZE_IMEM_8822C, ++ FWCD_SIZE_EMEM_8822C, ++ FWCD_SIZE_ROM_8822C, ++}; ++ ++static const struct rtw_fwcd_segs rtw8822c_fwcd_segs = { ++ .segs = __fwcd_segs_8822c, ++ .num = ARRAY_SIZE(__fwcd_segs_8822c), ++}; ++ ++static int rtw8822c_dump_fw_crash(struct rtw_dev *rtwdev) ++{ ++#define __dump_fw_8822c(_dev, _mem) \ ++ rtw_dump_fw(_dev, OCPBASE_ ## _mem ## _88XX, \ ++ FWCD_SIZE_ ## _mem ## _8822C, RTW_FWCD_ ## _mem) ++ int ret; ++ ++ ret = rtw_dump_reg(rtwdev, 0x0, FWCD_SIZE_REG_8822C); ++ if (ret) ++ return ret; ++ ret = __dump_fw_8822c(rtwdev, DMEM); ++ if (ret) ++ return ret; ++ ret = __dump_fw_8822c(rtwdev, IMEM); ++ if (ret) ++ return ret; ++ ret = __dump_fw_8822c(rtwdev, EMEM); ++ if (ret) ++ return ret; ++ ret = __dump_fw_8822c(rtwdev, ROM); ++ if (ret) ++ return ret; ++ ++ return 0; ++ ++#undef __dump_fw_8822c ++} ++ + static void rtw8822c_rstb_3wire(struct rtw_dev *rtwdev, bool enable) + { + if (enable) { +@@ -1707,10 +2488,11 @@ static void rtw8822c_config_cck_tx_path(struct rtw_dev *rtwdev, u8 tx_path, + else + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8); + } ++ rtw8822c_bb_reset(rtwdev); + } + + static void rtw8822c_config_ofdm_tx_path(struct rtw_dev *rtwdev, u8 tx_path, +- bool is_tx2_path) ++ enum rtw_bb_path tx_path_sel_1ss) + { + if (tx_path == BB_PATH_A) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x11); +@@ -1719,21 +2501,28 @@ static void rtw8822c_config_ofdm_tx_path(struct rtw_dev *rtwdev, u8 tx_path, + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x12); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xff, 0x0); + } else { +- if (is_tx2_path) { ++ if (tx_path_sel_1ss == BB_PATH_AB) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x33); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xffff, 0x0404); +- } else { ++ } else if (tx_path_sel_1ss == BB_PATH_B) { ++ rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x32); ++ rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xffff, 0x0400); ++ } else if (tx_path_sel_1ss == BB_PATH_A) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x31); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xffff, 0x0400); + } + } ++ rtw8822c_bb_reset(rtwdev); + } + + static void rtw8822c_config_tx_path(struct rtw_dev *rtwdev, u8 tx_path, ++ enum rtw_bb_path tx_path_sel_1ss, ++ enum rtw_bb_path tx_path_cck, + bool is_tx2_path) + { +- rtw8822c_config_cck_tx_path(rtwdev, tx_path, is_tx2_path); +- rtw8822c_config_ofdm_tx_path(rtwdev, tx_path, is_tx2_path); ++ rtw8822c_config_cck_tx_path(rtwdev, tx_path_cck, is_tx2_path); ++ rtw8822c_config_ofdm_tx_path(rtwdev, tx_path, tx_path_sel_1ss); ++ rtw8822c_bb_reset(rtwdev); + } + + static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, +@@ -1749,7 +2538,8 @@ static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + rtw_write32_mask(rtwdev, REG_ORITXCODE2, MASK20BITS, 0x11111); + + rtw8822c_config_rx_path(rtwdev, rx_path); +- rtw8822c_config_tx_path(rtwdev, tx_path, is_tx2_path); ++ rtw8822c_config_tx_path(rtwdev, tx_path, BB_PATH_A, BB_PATH_A, ++ is_tx2_path); + + rtw8822c_toggle_igi(rtwdev); + } +@@ -1763,6 +2553,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + s8 rx_power[RTW_RF_PATH_MAX]; + s8 min_rx_power = -120; + u8 rssi; ++ u8 channel; + int path; + + rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status); +@@ -1783,6 +2574,11 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + rx_power[RF_PATH_A] -= 110; + rx_power[RF_PATH_B] -= 110; + ++ channel = GET_PHY_STAT_P0_CHANNEL(phy_status); ++ if (channel == 0) ++ channel = rtwdev->hal.current_channel; ++ rtw_set_rx_freq_band(pkt_stat, channel); ++ + pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A]; + pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B]; + +@@ -1800,6 +2596,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) + { ++ struct rtw_path_div *p_div = &rtwdev->dm_path_div; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 rxsc, bw; + s8 min_rx_power = -120; +@@ -1807,6 +2604,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + u8 evm_dbm = 0; + u8 rssi; + int path; ++ u8 channel; + + if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0) + rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status); +@@ -1820,6 +2618,9 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + else + bw = RTW_CHANNEL_WIDTH_20; + ++ channel = GET_PHY_STAT_P1_CHANNEL(phy_status); ++ rtw_set_rx_freq_band(pkt_stat, channel); ++ + pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; + pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 2); +@@ -1842,6 +2643,13 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + for (path = 0; path <= rtwdev->hal.rf_path_num; path++) { + rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1); + dm_info->rssi[path] = rssi; ++ if (path == RF_PATH_A) { ++ p_div->path_a_sum += rssi; ++ p_div->path_a_cnt++; ++ } else if (path == RF_PATH_B) { ++ p_div->path_b_sum += rssi; ++ p_div->path_b_cnt++; ++ } + dm_info->rx_snr[path] = pkt_stat->rx_snr[path] >> 1; + dm_info->cfo_tail[path] = (pkt_stat->cfo_tail[path] * 5) >> 1; + +@@ -1855,6 +2663,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + } + dm_info->rx_evm_dbm[path] = evm_dbm; + } ++ rtw_phy_parsing_cfo(rtwdev, pkt_stat); + } + + static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, +@@ -1910,6 +2719,7 @@ static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, + + hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + + pkt_stat->drv_info_sz); ++ pkt_stat->hdr = hdr; + if (pkt_stat->phy_status) { + phy_status = rx_desc + desc_sz + pkt_stat->shift; + query_phy_status(rtwdev, phy_status, pkt_stat); +@@ -2006,7 +2816,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev, + case BB_PATH_AB: + break; + default: +- rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); ++ rtw_warn(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); + return -EINVAL; + } + +@@ -2016,7 +2826,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev, + case BB_PATH_AB: + break; + default: +- rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); ++ rtw_warn(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); + return -EINVAL; + } + +@@ -2131,20 +2941,17 @@ static void rtw8822c_do_iqk(struct rtw_dev *rtwdev) + { + struct rtw_iqk_para para = {0}; + u8 iqk_chk; +- int counter; ++ int ret; + + para.clear = 1; + rtw_fw_do_iqk(rtwdev, ¶); + +- for (counter = 0; counter < 300; counter++) { +- iqk_chk = rtw_read8(rtwdev, REG_RPT_CIP); +- if (iqk_chk == 0xaa) +- break; +- msleep(20); +- } +- rtw_write8(rtwdev, REG_IQKSTAT, 0x0); ++ ret = read_poll_timeout(rtw_read8, iqk_chk, iqk_chk == IQK_DONE_8822C, ++ 20000, 300000, false, rtwdev, REG_RPT_CIP); ++ if (ret) ++ rtw_warn(rtwdev, "failed to poll iqk status bit\n"); + +- rtw_dbg(rtwdev, RTW_DBG_RFK, "iqk counter=%d\n", counter); ++ rtw_write8(rtwdev, REG_IQKSTAT, 0x0); + } + + /* for coex */ +@@ -2153,28 +2960,28 @@ static void rtw8822c_coex_cfg_init(struct rtw_dev *rtwdev) + /* enable TBTT nterrupt */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + +- /* BT report packet sample rate */ ++ /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ +- rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); ++ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); +- rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); ++ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); + /* wl tx signal to PTA not case EDCCA */ + rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN); + /* GNT_BT=1 while select both */ +- rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); +- /* BT_CCA = ~GNT_WL_BB, (not or GNT_BT_BB, LTE_Rx */ ++ rtw_write16_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); ++ /* BT_CCA = ~GNT_WL_BB, not or GNT_BT_BB, LTE_Rx */ + rtw_write8_clr(rtwdev, REG_DUMMY_PAGE4_V1, BIT_BTCCA_CTRL); + + /* to avoid RF parameter error */ +- rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, 0x40000); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODOPT, 0xfffff, 0x40000); + } + + static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) +@@ -2207,41 +3014,62 @@ static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) + * enable "DAC off if GNT_WL = 0" for non-shared-antenna + * disable 0x1c30[22] = 0, + * enable: 0x1c30[22] = 1, 0x1c38[12] = 0, 0x1c38[28] = 1 +- * +- * disable WL-S1 BB chage RF mode if GNT_BT ++ */ ++ if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { ++ rtw_write8_mask(rtwdev, REG_ANAPAR + 2, ++ BIT_ANAPAR_BTPS >> 16, 0); ++ } else { ++ rtw_write8_mask(rtwdev, REG_ANAPAR + 2, ++ BIT_ANAPAR_BTPS >> 16, 1); ++ rtw_write8_mask(rtwdev, REG_RSTB_SEL + 1, ++ BIT_DAC_OFF_ENABLE, 0); ++ rtw_write8_mask(rtwdev, REG_RSTB_SEL + 3, ++ BIT_DAC_OFF_ENABLE, 1); ++ } ++ ++ /* disable WL-S1 BB chage RF mode if GNT_BT + * since RF TRx mask can do it + */ +- rtw_write8_mask(rtwdev, 0x1c32, BIT(6), 1); +- rtw_write8_mask(rtwdev, 0x1c39, BIT(4), 0); +- rtw_write8_mask(rtwdev, 0x1c3b, BIT(4), 1); +- rtw_write8_mask(rtwdev, 0x4160, BIT(3), 1); ++ rtw_write8_mask(rtwdev, REG_IGN_GNTBT4, ++ BIT_PI_IGNORE_GNT_BT, 1); + + /* disable WL-S0 BB chage RF mode if wifi is at 5G, + * or antenna path is separated + */ +- if (coex_stat->wl_coex_mode == COEX_WLINK_5G || ++ if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { ++ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1, ++ BIT_PI_IGNORE_GNT_BT, 1); ++ rtw_write8_mask(rtwdev, REG_NOMASK_TXBT, ++ BIT_NOMASK_TXBT_ENABLE, 1); ++ } else if (coex_stat->wl_coex_mode == COEX_WLINK_5G || + coex->under_5g || !efuse->share_ant) { + if (coex_stat->kt_ver >= 3) { +- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0); +- rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 1); ++ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1, ++ BIT_PI_IGNORE_GNT_BT, 0); ++ rtw_write8_mask(rtwdev, REG_NOMASK_TXBT, ++ BIT_NOMASK_TXBT_ENABLE, 1); + } else { +- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 1); ++ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1, ++ BIT_PI_IGNORE_GNT_BT, 1); + } + } else { + /* shared-antenna */ +- rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0); +- if (coex_stat->kt_ver >= 3) +- rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 0); ++ rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1, ++ BIT_PI_IGNORE_GNT_BT, 0); ++ if (coex_stat->kt_ver >= 3) { ++ rtw_write8_mask(rtwdev, REG_NOMASK_TXBT, ++ BIT_NOMASK_TXBT_ENABLE, 0); ++ } + } + } + + static void rtw8822c_coex_cfg_gnt_debug(struct rtw_dev *rtwdev) + { +- rtw_write8_mask(rtwdev, 0x66, BIT(4), 0); +- rtw_write8_mask(rtwdev, 0x67, BIT(0), 0); +- rtw_write8_mask(rtwdev, 0x42, BIT(3), 0); +- rtw_write8_mask(rtwdev, 0x65, BIT(7), 0); +- rtw_write8_mask(rtwdev, 0x73, BIT(3), 0); ++ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT_BTGP_SPI_EN >> 16, 0); ++ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT_BTGP_JTAG_EN >> 24, 0); ++ rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT_FSPI_EN >> 16, 0); ++ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 1, BIT_LED1DIS >> 8, 0); ++ rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT_DBG_GNT_WL_BT >> 24, 0); + } + + static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev) +@@ -2262,9 +3090,9 @@ static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev) + coex_rfe->wlg_at_btg = false; + + /* disable LTE coex in wifi side */ +- rtw_coex_write_indirect_reg(rtwdev, 0x38, BIT_LTE_COEX_EN, 0x0); +- rtw_coex_write_indirect_reg(rtwdev, 0xa0, MASKLWORD, 0xffff); +- rtw_coex_write_indirect_reg(rtwdev, 0xa4, MASKLWORD, 0xffff); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0x0); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff); ++ rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff); + } + + static void rtw8822c_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) +@@ -2289,16 +3117,22 @@ static void rtw8822c_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) + coex_dm->cur_wl_rx_low_gain_en = low_gain; + + if (coex_dm->cur_wl_rx_low_gain_en) { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table On!\n"); ++ + /* set Rx filter corner RCK offset */ +- rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x22); +- rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x36); +- rtw_write_rf(rtwdev, RF_PATH_B, 0xde, 0xfffff, 0x22); +- rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x36); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, RFREG_MASK, 0x22); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, RFREG_MASK, 0x36); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, RFREG_MASK, 0x22); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, RFREG_MASK, 0x36); ++ + } else { ++ rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Hi-Li Table Off!\n"); ++ + /* set Rx filter corner RCK offset */ +- rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x20); +- rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x0); +- rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x0); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, RFREG_MASK, 0x20); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, RFREG_MASK, 0x0); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, RFREG_MASK, 0x20); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, RFREG_MASK, 0x0); + } + } + +@@ -2463,7 +3297,7 @@ static void rtw8822c_dpk_rxbb_dc_cal(struct rtw_dev *rtwdev, u8 path) + static u8 rtw8822c_dpk_dc_corr_check(struct rtw_dev *rtwdev, u8 path) + { + u16 dc_i, dc_q; +- u8 corr_val, corr_idx; ++ u8 corr_idx; + + rtw_write32(rtwdev, REG_RXSRAM_CTL, 0x000900f0); + dc_i = (u16)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(27, 16)); +@@ -2476,7 +3310,7 @@ static u8 rtw8822c_dpk_dc_corr_check(struct rtw_dev *rtwdev, u8 path) + + rtw_write32(rtwdev, REG_RXSRAM_CTL, 0x000000f0); + corr_idx = (u8)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(7, 0)); +- corr_val = (u8)rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(15, 8)); ++ rtw_read32_mask(rtwdev, REG_STAT_RPT, GENMASK(15, 8)); + + if (dc_i > 200 || dc_q > 200 || corr_idx < 40 || corr_idx > 65) + return 1; +@@ -2523,9 +3357,9 @@ static void rtw8822c_dpk_pre_setting(struct rtw_dev *rtwdev) + rtw_write_rf(rtwdev, path, RF_RXAGC_OFFSET, RFREG_MASK, 0x0); + rtw_write32(rtwdev, REG_NCTL0, 0x8 | (path << 1)); + if (rtwdev->dm_info.dpk_info.dpk_band == RTW_BAND_2G) +- rtw_write32(rtwdev, REG_DPD_LUT3, 0x1f100000); ++ rtw_write32(rtwdev, REG_DPD_CTL1_S1, 0x1f100000); + else +- rtw_write32(rtwdev, REG_DPD_LUT3, 0x1f0d0000); ++ rtw_write32(rtwdev, REG_DPD_CTL1_S1, 0x1f0d0000); + rtw_write32_mask(rtwdev, REG_DPD_LUT0, BIT_GLOSS_DB, 0x4); + rtw_write32_mask(rtwdev, REG_IQK_CTL1, BIT_TX_CFIR, 0x3); + } +@@ -2543,11 +3377,11 @@ static u32 rtw8822c_dpk_rf_setting(struct rtw_dev *rtwdev, u8 path) + + rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_TX_GAIN, 0x1); + rtw_write_rf(rtwdev, path, RF_DEBUG, BIT_DE_PWR_TRIM, 0x1); +- rtw_write_rf(rtwdev, path, RF_TX_GAIN_OFFSET, BIT_TX_OFFSET_VAL, 0x0); ++ rtw_write_rf(rtwdev, path, RF_TX_GAIN_OFFSET, BIT_BB_GAIN, 0x0); + rtw_write_rf(rtwdev, path, RF_TX_GAIN, RFREG_MASK, ori_txbb); + + if (rtwdev->dm_info.dpk_info.dpk_band == RTW_BAND_2G) { +- rtw_write_rf(rtwdev, path, RF_TX_GAIN_OFFSET, BIT_LB_ATT, 0x1); ++ rtw_write_rf(rtwdev, path, RF_TX_GAIN_OFFSET, BIT_RF_GAIN, 0x1); + rtw_write_rf(rtwdev, path, RF_RXG_GAIN, BIT_RXG_GAIN, 0x0); + } else { + rtw_write_rf(rtwdev, path, RF_TXA_LB_SW, BIT_TXA_LB_ATT, 0x0); +@@ -3294,9 +4128,9 @@ static void rtw8822c_dpk_reload_data(struct rtw_dev *rtwdev) + rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SUBPAGE, + 0x8 | (path << 1)); + if (dpk_info->dpk_band == RTW_BAND_2G) +- rtw_write32(rtwdev, REG_DPD_LUT3, 0x1f100000); ++ rtw_write32(rtwdev, REG_DPD_CTL1_S1, 0x1f100000); + else +- rtw_write32(rtwdev, REG_DPD_LUT3, 0x1f0d0000); ++ rtw_write32(rtwdev, REG_DPD_CTL1_S1, 0x1f0d0000); + + rtw_write8(rtwdev, REG_DPD_AGC, dpk_info->dpk_txagc[path]); + +@@ -3380,8 +4214,11 @@ static void rtw8822c_do_dpk(struct rtw_dev *rtwdev) + + static void rtw8822c_phy_calibration(struct rtw_dev *rtwdev) + { ++ rtw8822c_rfk_power_save(rtwdev, false); ++ rtw8822c_do_gapk(rtwdev); + rtw8822c_do_iqk(rtwdev); + rtw8822c_do_dpk(rtwdev); ++ rtw8822c_rfk_power_save(rtwdev, true); + } + + static void rtw8822c_dpk_track(struct rtw_dev *rtwdev) +@@ -3416,6 +4253,128 @@ static void rtw8822c_dpk_track(struct rtw_dev *rtwdev) + } + } + ++#define XCAP_EXTEND(val) ({typeof(val) _v = (val); _v | _v << 7; }) ++static void rtw8822c_set_crystal_cap_reg(struct rtw_dev *rtwdev, u8 crystal_cap) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ u32 val = 0; ++ ++ val = XCAP_EXTEND(crystal_cap); ++ cfo->crystal_cap = crystal_cap; ++ rtw_write32_mask(rtwdev, REG_ANAPAR_XTAL_0, BIT_XCAP_0, val); ++} ++ ++static void rtw8822c_set_crystal_cap(struct rtw_dev *rtwdev, u8 crystal_cap) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ ++ if (cfo->crystal_cap == crystal_cap) ++ return; ++ ++ rtw8822c_set_crystal_cap_reg(rtwdev, crystal_cap); ++} ++ ++static void rtw8822c_cfo_tracking_reset(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ ++ cfo->is_adjust = true; ++ ++ if (cfo->crystal_cap > rtwdev->efuse.crystal_cap) ++ rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap - 1); ++ else if (cfo->crystal_cap < rtwdev->efuse.crystal_cap) ++ rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap + 1); ++} ++ ++static void rtw8822c_cfo_init(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ ++ cfo->crystal_cap = rtwdev->efuse.crystal_cap; ++ cfo->is_adjust = true; ++} ++ ++#define REPORT_TO_KHZ(val) ({typeof(val) _v = (val); (_v << 1) + (_v >> 1); }) ++static s32 rtw8822c_cfo_calc_avg(struct rtw_dev *rtwdev, u8 path_num) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ s32 cfo_avg, cfo_path_sum = 0, cfo_rpt_sum; ++ u8 i; ++ ++ for (i = 0; i < path_num; i++) { ++ cfo_rpt_sum = REPORT_TO_KHZ(cfo->cfo_tail[i]); ++ ++ if (cfo->cfo_cnt[i]) ++ cfo_avg = cfo_rpt_sum / cfo->cfo_cnt[i]; ++ else ++ cfo_avg = 0; ++ ++ cfo_path_sum += cfo_avg; ++ } ++ ++ for (i = 0; i < path_num; i++) { ++ cfo->cfo_tail[i] = 0; ++ cfo->cfo_cnt[i] = 0; ++ } ++ ++ return cfo_path_sum / path_num; ++} ++ ++static void rtw8822c_cfo_need_adjust(struct rtw_dev *rtwdev, s32 cfo_avg) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ ++ if (!cfo->is_adjust) { ++ if (abs(cfo_avg) > CFO_TRK_ENABLE_TH) ++ cfo->is_adjust = true; ++ } else { ++ if (abs(cfo_avg) <= CFO_TRK_STOP_TH) ++ cfo->is_adjust = false; ++ } ++ ++ if (!rtw_coex_disabled(rtwdev)) { ++ cfo->is_adjust = false; ++ rtw8822c_set_crystal_cap(rtwdev, rtwdev->efuse.crystal_cap); ++ } ++} ++ ++static void rtw8822c_cfo_track(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ struct rtw_cfo_track *cfo = &dm_info->cfo_track; ++ u8 path_num = rtwdev->hal.rf_path_num; ++ s8 crystal_cap = cfo->crystal_cap; ++ s32 cfo_avg = 0; ++ ++ if (rtwdev->sta_cnt != 1) { ++ rtw8822c_cfo_tracking_reset(rtwdev); ++ return; ++ } ++ ++ if (cfo->packet_count == cfo->packet_count_pre) ++ return; ++ ++ cfo->packet_count_pre = cfo->packet_count; ++ cfo_avg = rtw8822c_cfo_calc_avg(rtwdev, path_num); ++ rtw8822c_cfo_need_adjust(rtwdev, cfo_avg); ++ ++ if (cfo->is_adjust) { ++ if (cfo_avg > CFO_TRK_ADJ_TH) ++ crystal_cap++; ++ else if (cfo_avg < -CFO_TRK_ADJ_TH) ++ crystal_cap--; ++ ++ crystal_cap = clamp_t(s8, crystal_cap, 0, XCAP_MASK); ++ rtw8822c_set_crystal_cap(rtwdev, (u8)crystal_cap); ++ } ++} ++ + static const struct rtw_phy_cck_pd_reg + rtw8822c_cck_pd_reg[RTW_CHANNEL_WIDTH_40 + 1][RTW_RF_PATH_MAX] = { + { +@@ -3463,6 +4422,10 @@ rtw8822c_phy_cck_pd_set_reg(struct rtw_dev *rtwdev, + rtw8822c_cck_pd_reg[bw][nrx].reg_cs, + rtw8822c_cck_pd_reg[bw][nrx].mask_cs, + cs); ++ ++ rtw_dbg(rtwdev, RTW_DBG_PHY, ++ "is_linked=%d, bw=%d, nrx=%d, cs_ratio=0x%x, pd_th=0x%x\n", ++ rtw_is_assoc(rtwdev), bw, nrx, cs, pd); + } + + static void rtw8822c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) +@@ -3476,6 +4439,10 @@ static void rtw8822c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl) + nrx = (u8)rtw_read32_mask(rtwdev, 0x1a2c, 0x60000); + bw = (u8)rtw_read32_mask(rtwdev, 0x9b0, 0xc); + ++ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d) bw=%d nr=%d cck_fa_avg=%d\n", ++ dm_info->cck_pd_lv[bw][nrx], new_lvl, bw, nrx, ++ dm_info->cck_fa_avg); ++ + if (dm_info->cck_pd_lv[bw][nrx] == new_lvl) + return; + +@@ -3575,6 +4542,51 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + ++static void rtw8822c_adaptivity_init(struct rtw_dev *rtwdev) ++{ ++ rtw_phy_set_edcca_th(rtwdev, RTW8822C_EDCCA_MAX, RTW8822C_EDCCA_MAX); ++ ++ /* mac edcca state setting */ ++ rtw_write32_clr(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA); ++ rtw_write32_set(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN); ++ ++ /* edcca decistion opt */ ++ rtw_write32_clr(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION); ++} ++ ++static void rtw8822c_adaptivity(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ s8 l2h, h2l; ++ u8 igi; ++ ++ igi = dm_info->igi_history[0]; ++ if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) { ++ l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB); ++ h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL; ++ } else { ++ if (igi < dm_info->l2h_th_ini - EDCCA_ADC_BACKOFF) ++ l2h = igi + EDCCA_ADC_BACKOFF; ++ else ++ l2h = dm_info->l2h_th_ini; ++ h2l = l2h - EDCCA_L2H_H2L_DIFF; ++ } ++ ++ rtw_phy_set_edcca_th(rtwdev, l2h, h2l); ++} ++ ++static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ size_t words; ++ ++ words = (pkt_info->pkt_offset * 8 + chip->tx_pkt_desc_sz) / 2; ++ ++ fill_txdesc_checksum_common(txdesc, words); ++} ++ + static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, +@@ -3913,6 +4925,8 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { + [0] = RTW_DEF_RFE(8822c, 0, 0), + [1] = RTW_DEF_RFE(8822c, 0, 0), + [2] = RTW_DEF_RFE(8822c, 0, 0), ++ [3] = RTW_DEF_RFE(8822c, 0, 0), ++ [4] = RTW_DEF_RFE(8822c, 0, 0), + [5] = RTW_DEF_RFE(8822c, 0, 5), + [6] = RTW_DEF_RFE(8822c, 0, 0), + }; +@@ -3976,6 +4990,7 @@ static struct rtw_chip_ops rtw8822c_ops = { + .query_rx_desc = rtw8822c_query_rx_desc, + .set_channel = rtw8822c_set_channel, + .mac_init = rtw8822c_mac_init, ++ .dump_fw_crash = rtw8822c_dump_fw_crash, + .read_rf = rtw_phy_read_rf, + .write_rf = rtw_phy_write_rf_reg_mix, + .set_tx_power_index = rtw8822c_set_tx_power_index, +@@ -3989,6 +5004,13 @@ static struct rtw_chip_ops rtw8822c_ops = { + .config_bfee = rtw8822c_bf_config_bfee, + .set_gid_table = rtw_bf_set_gid_table, + .cfg_csi_rate = rtw_bf_cfg_csi_rate, ++ .adaptivity_init = rtw8822c_adaptivity_init, ++ .adaptivity = rtw8822c_adaptivity, ++ .cfo_init = rtw8822c_cfo_init, ++ .cfo_track = rtw8822c_cfo_track, ++ .config_tx_path = rtw8822c_config_tx_path, ++ .config_txrx_mode = rtw8822c_config_trx_mode, ++ .fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum, + + .coex_set_init = rtw8822c_coex_cfg_init, + .coex_set_ant_switch = NULL, +@@ -4007,14 +5029,14 @@ static const struct coex_table_para table_sant_8822c[] = { + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ +- {0x6a5a6a5a, 0xaaaaaaaa}, ++ {0x6a5a5555, 0xaaaaaaaa}, + {0x6a5a56aa, 0x6a5a56aa}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-10 */ +- {0x66555555, 0xfafafafa}, ++ {0x66555555, 0x6a5a5aaa}, + {0x66555555, 0x5a5a5aaa}, +- {0x66555555, 0x5aaa5aaa}, ++ {0x66555555, 0x6aaa5aaa}, + {0x66555555, 0xaaaa5aaa}, + {0x66555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, +@@ -4024,13 +5046,18 @@ static const struct coex_table_para table_sant_8822c[] = { + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, +- {0xffffffff, 0x6a5a5a5a}, ++ {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x55555555}, +- {0xffffffff, 0x6a5a5aaa}, /* case-25 */ ++ {0xffffffff, 0x5a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, + {0x55555555, 0x6a5a6a5a}, +- {0x66556655, 0x66556655} ++ {0x66556655, 0x66556655}, ++ {0x66556aaa, 0x6a5a6aaa}, /*case-30*/ ++ {0xffffffff, 0x5aaa5aaa}, ++ {0x56555555, 0x5a5a5aaa}, ++ {0xdaffdaff, 0xdaffdaff}, ++ {0xddffddff, 0xddffddff}, + }; + + /* Non-Shared-Antenna Coex Table */ +@@ -4050,12 +5077,12 @@ static const struct coex_table_para table_nsant_8822c[] = { + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, +- {0xaaffffaa, 0xfafafafa}, /* case-115 */ ++ {0xffff55ff, 0xffff55ff}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, + {0xffffffff, 0x5afa5afa}, +- {0xffffffff, 0xaaaaaaaa},/* case-120 */ ++ {0xffffffff, 0xaaaaaaaa}, /* case-120 */ + {0x55ff55ff, 0x5afa5afa}, + {0x55ff55ff, 0xaaaaaaaa}, + {0x55ff55ff, 0x55ff55ff} +@@ -4064,7 +5091,7 @@ static const struct coex_table_para table_nsant_8822c[] = { + /* Shared-Antenna TDMA */ + static const struct coex_tdma_para tdma_sant_8822c[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ +- { {0x61, 0x45, 0x03, 0x11, 0x11} }, ++ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, +@@ -4079,7 +5106,7 @@ static const struct coex_tdma_para tdma_sant_8822c[] = { + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ +- { {0x51, 0x45, 0x03, 0x10, 0x10} }, ++ { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, +@@ -4087,7 +5114,7 @@ static const struct coex_tdma_para tdma_sant_8822c[] = { + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, +- { {0x65, 0x10, 0x03, 0x11, 0x11} }, ++ { {0x65, 0x10, 0x03, 0x11, 0x10} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} }, + { {0x61, 0x08, 0x03, 0x11, 0x11} } +@@ -4115,7 +5142,8 @@ static const struct coex_tdma_para tdma_nsant_8822c[] = { + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, +- { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */ ++ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */ ++ { {0x51, 0x08, 0x03, 0x10, 0x50} } + }; + + /* rssi in percentage % (dbm = % - 100) */ +@@ -4130,7 +5158,8 @@ static const struct coex_rf_para rf_para_tx_8822c[] = { + {8, 17, true, 4}, + {7, 18, true, 4}, + {6, 19, true, 4}, +- {5, 20, true, 4} ++ {5, 20, true, 4}, ++ {0, 21, true, 4} /* for gamg hid */ + }; + + static const struct coex_rf_para rf_para_rx_8822c[] = { +@@ -4139,11 +5168,10 @@ static const struct coex_rf_para rf_para_rx_8822c[] = { + {3, 24, true, 5}, + {2, 26, true, 5}, + {1, 27, true, 5}, +- {0, 28, true, 5} ++ {0, 28, true, 5}, ++ {0, 28, true, 5} /* for gamg hid */ + }; + +-static_assert(ARRAY_SIZE(rf_para_tx_8822c) == ARRAY_SIZE(rf_para_rx_8822c)); +- + static const u8 + rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = { + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, +@@ -4267,6 +5295,15 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { + .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, + }; + ++static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { ++ [EDCCA_TH_L2H_IDX] = { ++ {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80 ++ }, ++ [EDCCA_TH_H2L_IDX] = { ++ {.addr = 0x84c, .mask = MASKBYTE3}, .offset = 0x80 ++ }, ++}; ++ + #ifdef CONFIG_PM + static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_GTK_REKEY_FAILURE | +@@ -4304,7 +5341,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = { + {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + }; + +-struct rtw_chip_info rtw8822c_hw_spec = { ++const struct rtw_chip_info rtw8822c_hw_spec = { + .ops = &rtw8822c_ops, + .id = RTW_CHIP_TYPE_8822C, + .fw_name = "rtw88/rtw8822c_fw.bin", +@@ -4319,13 +5356,16 @@ struct rtw_chip_info rtw8822c_hw_spec = { + .txff_size = 262144, + .rxff_size = 24576, + .fw_rxff_size = 12288, ++ .rsvd_drv_pg_num = 16, + .txgi_factor = 2, + .is_pwr_by_rate_dec = false, + .max_power_index = 0x7f, + .csi_buf_pg_num = 50, + .band = RTW_BAND_2G | RTW_BAND_5G, +- .page_size = 128, ++ .page_size = TX_PAGE_SIZE, + .dig_min = 0x20, ++ .default_1ss_tx_path = BB_PATH_A, ++ .path_div_supported = true, + .ht_supported = true, + .vht_supported = true, + .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK) | BIT(LPS_DEEP_MODE_PG), +@@ -4356,16 +5396,24 @@ struct rtw_chip_info rtw8822c_hw_spec = { + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, + .rx_ldpc = true, ++ .tx_stbc = true, ++ .edcca_th = rtw8822c_edcca_th, ++ .l2h_th_ini_cs = 60, ++ .l2h_th_ini_ad = 45, ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2, + + #ifdef CONFIG_PM + .wow_fw_name = "rtw88/rtw8822c_wow_fw.bin", + .wowlan_stub = &rtw_wowlan_stub_8822c, + .max_sched_scan_ssids = 4, + #endif +- .coex_para_ver = 0x20070217, +- .bt_desired_ver = 0x17, ++ .max_scan_ie_len = (RTW_PROBE_PG_CNT - 1) * TX_PAGE_SIZE, ++ .coex_para_ver = 0x22020720, ++ .bt_desired_ver = 0x20, + .scbd_support = true, + .new_scbd10_def = true, ++ .ble_hid_profile_support = true, ++ .wl_mimo_ps_support = true, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_DBM, + .ant_isolation = 15, +@@ -4392,6 +5440,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { + .coex_info_hw_regs = coex_info_hw_regs_8822c, + + .fw_fifo_addr = {0x780, 0x700, 0x780, 0x660, 0x650, 0x680}, ++ .fwcd_segs = &rtw8822c_fwcd_segs, + }; + EXPORT_SYMBOL(rtw8822c_hw_spec); + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h +index 32b4771e04d0..1bc0e7f5d6bb 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h +@@ -16,6 +16,11 @@ struct rtw8822cu_efuse { + u8 res2[0x3d]; + }; + ++struct rtw8822cs_efuse { ++ u8 res0[0x4a]; /* 0x120 */ ++ u8 mac_addr[ETH_ALEN]; /* 0x16a */ ++} __packed; ++ + struct rtw8822ce_efuse { + u8 mac_addr[ETH_ALEN]; /* 0x120 */ + u8 vender_id[2]; +@@ -91,8 +96,9 @@ struct rtw8822c_efuse { + u8 res9; + u8 res10[0x42]; + union { +- struct rtw8822cu_efuse u; + struct rtw8822ce_efuse e; ++ struct rtw8822cu_efuse u; ++ struct rtw8822cs_efuse s; + }; + }; + +@@ -118,6 +124,8 @@ enum rtw8822c_dpk_one_shot_action { + void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev, + const struct rtw_table *tbl); + ++extern const struct rtw_chip_info rtw8822c_hw_spec; ++ + #define RTW_DECL_TABLE_DPK(name) \ + const struct rtw_table name ## _tbl = { \ + .data = name, \ +@@ -137,6 +145,8 @@ const struct rtw_table name ## _tbl = { \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0)) + #define GET_PHY_STAT_P0_GAIN_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(21, 16)) ++#define GET_PHY_STAT_P0_CHANNEL(phy_stat) \ ++ le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16)) + #define GET_PHY_STAT_P0_GAIN_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(29, 24)) + +@@ -149,6 +159,8 @@ const struct rtw_table name ## _tbl = { \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8)) + #define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12)) ++#define GET_PHY_STAT_P1_CHANNEL(phy_stat) \ ++ le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16)) + #define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0)) + #define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \ +@@ -162,179 +174,253 @@ const struct rtw_table name ## _tbl = { \ + #define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8)) + ++#define RTW8822C_EDCCA_MAX 0x7f + #define REG_ANAPARLDO_POW_MAC 0x0029 + #define BIT_LDOE25_PON BIT(0) +-#define REG_RRSR 0x0440 +-#define BITS_RRSR_RSC (BIT(21) | BIT(22)) ++#define XCAP_MASK GENMASK(6, 0) ++#define CFO_TRK_ENABLE_TH 20 ++#define CFO_TRK_STOP_TH 10 ++#define CFO_TRK_ADJ_TH 10 + +-#define REG_TXDFIR0 0x808 +-#define REG_DFIRBW 0x810 +-#define REG_ANTMAP0 0x820 +-#define REG_ANTMAP 0x824 +-#define REG_DYMPRITH 0x86c +-#define REG_DYMENTH0 0x870 +-#define REG_DYMENTH 0x874 +-#define REG_SBD 0x88c ++#define REG_TXDFIR0 0x808 ++#define REG_DFIRBW 0x810 ++#define REG_ANTMAP0 0x820 ++#define BIT_ANT_PATH GENMASK(1, 0) ++#define REG_ANTMAP 0x824 ++#define REG_EDCCA_DECISION 0x844 ++#define BIT_EDCCA_OPTION GENMASK(30, 29) ++#define REG_DYMPRITH 0x86c ++#define REG_DYMENTH0 0x870 ++#define REG_DYMENTH 0x874 ++#define REG_SBD 0x88c + #define BITS_SUBTUNE GENMASK(15, 12) +-#define REG_DYMTHMIN 0x8a4 +-#define REG_TXBWCTL 0x9b0 +-#define REG_TXCLK 0x9b4 +-#define REG_SCOTRK 0xc30 +-#define REG_MRCM 0xc38 +-#define REG_AGCSWSH 0xc44 +-#define REG_ANTWTPD 0xc54 +-#define REG_PT_CHSMO 0xcbc ++#define REG_DYMTHMIN 0x8a4 ++ ++#define REG_TXBWCTL 0x9b0 ++#define REG_TXCLK 0x9b4 ++ ++#define REG_SCOTRK 0xc30 ++#define REG_MRCM 0xc38 ++#define REG_AGCSWSH 0xc44 ++#define REG_ANTWTPD 0xc54 ++#define REG_PT_CHSMO 0xcbc + #define BIT_PT_OPT BIT(21) +-#define REG_ORITXCODE 0x1800 +-#define REG_3WIRE 0x180c ++ ++#define REG_ORITXCODE 0x1800 ++#define BIT_PATH_EN BIT(31) ++#define REG_3WIRE 0x180c ++#define BIT_DIS_SHARERX_TXGAT BIT(27) + #define BIT_3WIRE_TX_EN BIT(0) + #define BIT_3WIRE_RX_EN BIT(1) ++#define BIT_3WIRE_EN GENMASK(1, 0) + #define BIT_3WIRE_PI_ON BIT(28) +-#define REG_ANAPAR_A 0x1830 ++#define REG_ANAPAR_A 0x1830 + #define BIT_ANAPAR_UPDATE BIT(29) +-#define REG_RXAGCCTL0 0x18ac ++#define REG_RFTXEN_GCK_A 0x1864 ++#define BIT_RFTXEN_GCK_FORCE_ON BIT(31) ++#define REG_DIS_SHARE_RX_A 0x186c ++#define BIT_TX_SCALE_0DB BIT(7) ++#define REG_RXAGCCTL0 0x18ac + #define BITS_RXAGC_CCK GENMASK(15, 12) + #define BITS_RXAGC_OFDM GENMASK(8, 4) +-#define REG_DCKA_I_0 0x18bc +-#define REG_DCKA_I_1 0x18c0 +-#define REG_DCKA_Q_0 0x18d8 +-#define REG_DCKA_Q_1 0x18dc +-#define REG_CCKSB 0x1a00 +-#define REG_RXCCKSEL 0x1a04 +-#define REG_BGCTRL 0x1a14 ++#define REG_DCKA_I_0 0x18bc ++#define REG_DCKA_I_1 0x18c0 ++#define REG_DCKA_Q_0 0x18d8 ++#define REG_DCKA_Q_1 0x18dc ++ ++#define REG_CCKSB 0x1a00 ++#define BIT_BBMODE GENMASK(2, 1) ++#define REG_RXCCKSEL 0x1a04 ++#define REG_BGCTRL 0x1a14 + #define BITS_RX_IQ_WEIGHT (BIT(8) | BIT(9)) +-#define REG_TXF0 0x1a20 +-#define REG_TXF1 0x1a24 +-#define REG_TXF2 0x1a28 +-#define REG_CCANRX 0x1a2c ++#define REG_TXF0 0x1a20 ++#define REG_TXF1 0x1a24 ++#define REG_TXF2 0x1a28 ++#define REG_CCANRX 0x1a2c + #define BIT_CCK_FA_RST (BIT(14) | BIT(15)) + #define BIT_OFDM_FA_RST (BIT(12) | BIT(13)) +-#define REG_CCK_FACNT 0x1a5c +-#define REG_CCKTXONLY 0x1a80 ++#define REG_CCK_FACNT 0x1a5c ++#define REG_CCKTXONLY 0x1a80 + #define BIT_BB_CCK_CHECK_EN BIT(18) +-#define REG_TXF3 0x1a98 +-#define REG_TXF4 0x1a9c +-#define REG_TXF5 0x1aa0 +-#define REG_TXF6 0x1aac +-#define REG_TXF7 0x1ab0 +-#define REG_CCK_SOURCE 0x1abc ++#define REG_TXF3 0x1a98 ++#define REG_TXF4 0x1a9c ++#define REG_TXF5 0x1aa0 ++#define REG_TXF6 0x1aac ++#define REG_TXF7 0x1ab0 ++#define REG_CCK_SOURCE 0x1abc + #define BIT_NBI_EN BIT(30) +-#define REG_IQKSTAT 0x1b10 +-#define REG_TXANT 0x1c28 +-#define REG_ENCCK 0x1c3c +-#define BIT_CCK_BLK_EN BIT(1) +-#define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1)) +-#define REG_CCAMSK 0x1c80 +-#define REG_RSTB 0x1c90 +-#define BIT_RSTB_3WIRE BIT(8) +-#define REG_RX_BREAK 0x1d2c +-#define BIT_COM_RX_GCK_EN BIT(31) +-#define REG_RXFNCTL 0x1d30 +-#define REG_RXIGI 0x1d70 +-#define REG_ENFN 0x1e24 +-#define REG_TXANTSEG 0x1e28 +-#define REG_TXLGMAP 0x1e2c +-#define REG_CCKPATH 0x1e5c +-#define REG_CNT_CTRL 0x1eb4 +-#define BIT_ALL_CNT_RST BIT(25) +-#define REG_OFDM_FACNT 0x2d00 +-#define REG_OFDM_FACNT1 0x2d04 +-#define REG_OFDM_FACNT2 0x2d08 +-#define REG_OFDM_FACNT3 0x2d0c +-#define REG_OFDM_FACNT4 0x2d10 +-#define REG_OFDM_FACNT5 0x2d20 +-#define REG_RPT_CIP 0x2d9c +-#define REG_OFDM_TXCNT 0x2de0 +-#define REG_ORITXCODE2 0x4100 +-#define REG_3WIRE2 0x410c +-#define REG_ANAPAR_B 0x4130 +-#define REG_RXAGCCTL 0x41ac +-#define REG_DCKB_I_0 0x41bc +-#define REG_DCKB_I_1 0x41c0 +-#define REG_DCKB_Q_0 0x41d8 +-#define REG_DCKB_Q_1 0x41dc +- +-#define RF_MODE_TRXAGC 0x00 +-#define RF_RXAGC_OFFSET 0x19 +-#define RF_BW_TRXBB 0x1a +-#define RF_TX_GAIN_OFFSET 0x55 +-#define RF_TX_GAIN 0x56 +-#define RF_TXA_LB_SW 0x63 +-#define RF_RXG_GAIN 0x87 +-#define RF_RXA_MIX_GAIN 0x8a +-#define RF_EXT_TIA_BW 0x8f +-#define RF_DEBUG 0xde + + #define REG_NCTL0 0x1b00 ++#define BIT_SEL_PATH GENMASK(2, 1) ++#define BIT_SUBPAGE GENMASK(3, 0) + #define REG_DPD_CTL0_S0 0x1b04 ++#define BIT_GS_PWSF GENMASK(27, 0) + #define REG_DPD_CTL1_S0 0x1b08 ++#define BIT_DPD_EN BIT(31) ++#define BIT_PS_EN BIT(7) ++#define REG_IQKSTAT 0x1b10 + #define REG_IQK_CTL1 0x1b20 ++#define BIT_TX_CFIR GENMASK(31, 30) ++#define BIT_CFIR_EN GENMASK(26, 24) ++#define BIT_BYPASS_DPD BIT(25) ++ ++#define REG_TX_TONE_IDX 0x1b2c + #define REG_DPD_LUT0 0x1b44 ++#define BIT_GLOSS_DB GENMASK(14, 12) + #define REG_DPD_CTL0_S1 0x1b5c +-#define REG_DPD_LUT3 0x1b60 + #define REG_DPD_CTL1_S1 0x1b60 + #define REG_DPD_AGC 0x1b67 ++#define REG_TABLE_SEL 0x1b98 ++#define BIT_I_GAIN GENMASK(19, 16) ++#define BIT_GAIN_RST BIT(15) ++#define BIT_Q_GAIN_SEL GENMASK(14, 12) ++#define BIT_Q_GAIN GENMASK(11, 0) ++#define REG_TX_GAIN_SET 0x1b9c ++#define BIT_GAPK_RPT_IDX GENMASK(11, 8) + #define REG_DPD_CTL0 0x1bb4 ++#define REG_SINGLE_TONE_SW 0x1bb8 ++#define BIT_IRQ_TEST_MODE BIT(20) + #define REG_R_CONFIG 0x1bcc ++#define BIT_INNER_LB BIT(21) ++#define BIT_IQ_SWITCH GENMASK(5, 0) ++#define BIT_2G_SWING 0x2d ++#define BIT_5G_SWING 0x36 + #define REG_RXSRAM_CTL 0x1bd4 ++#define BIT_RPT_EN BIT(21) ++#define BIT_RPT_SEL GENMASK(20, 16) ++#define BIT_DPD_CLK GENMASK(7, 4) + #define REG_DPD_CTL11 0x1be4 + #define REG_DPD_CTL12 0x1be8 + #define REG_DPD_CTL15 0x1bf4 + #define REG_DPD_CTL16 0x1bf8 + #define REG_STAT_RPT 0x1bfc ++#define BIT_RPT_DGAIN GENMASK(27, 16) ++#define BIT_GAPK_RPT0 GENMASK(3, 0) ++#define BIT_GAPK_RPT1 GENMASK(7, 4) ++#define BIT_GAPK_RPT2 GENMASK(11, 8) ++#define BIT_GAPK_RPT3 GENMASK(15, 12) ++#define BIT_GAPK_RPT4 GENMASK(19, 16) ++#define BIT_GAPK_RPT5 GENMASK(23, 20) ++#define BIT_GAPK_RPT6 GENMASK(27, 24) ++#define BIT_GAPK_RPT7 GENMASK(31, 28) ++ ++#define REG_TXANT 0x1c28 ++#define REG_IQK_CTRL 0x1c38 ++#define REG_ENCCK 0x1c3c ++#define BIT_CCK_BLK_EN BIT(1) ++#define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1)) ++#define REG_CCAMSK 0x1c80 ++#define REG_RSTB 0x1c90 ++#define BIT_RSTB_3WIRE BIT(8) ++#define REG_CH_DELAY_EXTR2 0x1cd0 ++#define BIT_TST_IQK2SET_SRC BIT(31) ++#define BIT_EN_IOQ_IQK_DPK BIT(30) ++#define BIT_IQK_DPK_RESET_SRC BIT(29) ++#define BIT_IQK_DPK_CLOCK_SRC BIT(28) ++ ++#define REG_RX_BREAK 0x1d2c ++#define BIT_COM_RX_GCK_EN BIT(31) ++#define REG_RXFNCTL 0x1d30 ++#define REG_CCA_OFF 0x1d58 ++#define BIT_CCA_ON_BY_PW GENMASK(11, 3) ++#define REG_RXIGI 0x1d70 ++ ++#define REG_ENFN 0x1e24 ++#define BIT_IQK_DPK_EN BIT(17) ++#define REG_TXANTSEG 0x1e28 ++#define BIT_ANTSEG GENMASK(3, 0) ++#define REG_TXLGMAP 0x1e2c ++#define REG_CCKPATH 0x1e5c ++#define REG_TX_FIFO 0x1e70 ++#define BIT_STOP_TX GENMASK(3, 0) ++#define REG_CNT_CTRL 0x1eb4 ++#define BIT_ALL_CNT_RST BIT(25) ++ ++#define REG_OFDM_FACNT 0x2d00 ++#define REG_OFDM_FACNT1 0x2d04 ++#define REG_OFDM_FACNT2 0x2d08 ++#define REG_OFDM_FACNT3 0x2d0c ++#define REG_OFDM_FACNT4 0x2d10 ++#define REG_OFDM_FACNT5 0x2d20 ++#define REG_RPT_CIP 0x2d9c ++#define BIT_RPT_CIP_STATUS GENMASK(7, 0) ++#define REG_OFDM_TXCNT 0x2de0 + ++#define REG_ORITXCODE2 0x4100 ++#define REG_3WIRE2 0x410c ++#define REG_ANAPAR_B 0x4130 ++#define REG_RFTXEN_GCK_B 0x4164 ++#define REG_DIS_SHARE_RX_B 0x416c + #define BIT_EXT_TIA_BW BIT(1) +-#define BIT_DE_TRXBW BIT(2) +-#define BIT_DE_TX_GAIN BIT(16) +-#define BIT_RXG_GAIN BIT(18) +-#define BIT_DE_PWR_TRIM BIT(19) +-#define BIT_INNER_LB BIT(21) +-#define BIT_BYPASS_DPD BIT(25) +-#define BIT_DPD_EN BIT(31) +-#define BIT_SUBPAGE GENMASK(3, 0) ++#define REG_RXAGCCTL 0x41ac ++#define REG_DCKB_I_0 0x41bc ++#define REG_DCKB_I_1 0x41c0 ++#define REG_DCKB_Q_0 0x41d8 ++#define REG_DCKB_Q_1 0x41dc ++ ++#define RF_MODE_TRXAGC 0x00 ++#define BIT_RF_MODE GENMASK(19, 16) ++#define BIT_RXAGC GENMASK(9, 5) + #define BIT_TXAGC GENMASK(4, 0) ++#define RF_RXAGC_OFFSET 0x19 ++#define RF_BW_TRXBB 0x1a ++#define BIT_TX_CCK_IND BIT(16) ++#define BIT_BW_TXBB GENMASK(14, 12) ++#define BIT_BW_RXBB GENMASK(11, 10) ++#define BIT_DBG_CCK_CCA BIT(1) ++#define RF_TX_GAIN_OFFSET 0x55 ++#define BIT_BB_GAIN GENMASK(18, 14) ++#define BIT_RF_GAIN GENMASK(4, 2) ++#define RF_TX_GAIN 0x56 + #define BIT_GAIN_TXBB GENMASK(4, 0) ++#define RF_IDAC 0x58 ++#define BIT_TX_MODE GENMASK(19, 8) ++#define RF_TX_RESULT 0x5f ++#define BIT_GAIN_TX_PAD_H GENMASK(11, 8) ++#define BIT_GAIN_TX_PAD_L GENMASK(7, 4) ++#define RF_PA 0x60 ++#define RF_PABIAS_2G_MASK GENMASK(15, 12) ++#define RF_PABIAS_5G_MASK GENMASK(19, 16) ++#define RF_TXA_LB_SW 0x63 ++#define BIT_TXA_LB_ATT GENMASK(15, 14) ++#define BIT_LB_SW GENMASK(13, 12) + #define BIT_LB_ATT GENMASK(4, 2) ++#define RF_RXG_GAIN 0x87 ++#define BIT_RXG_GAIN BIT(18) ++#define RF_RXA_MIX_GAIN 0x8a + #define BIT_RXA_MIX_GAIN GENMASK(4, 3) +-#define BIT_IQ_SWITCH GENMASK(5, 0) +-#define BIT_DPD_CLK GENMASK(7, 4) +-#define BIT_RXAGC GENMASK(9, 5) +-#define BIT_BW_RXBB GENMASK(11, 10) +-#define BIT_LB_SW GENMASK(13, 12) +-#define BIT_BW_TXBB GENMASK(14, 12) +-#define BIT_GLOSS_DB GENMASK(14, 12) +-#define BIT_TXA_LB_ATT GENMASK(15, 14) +-#define BIT_TX_OFFSET_VAL GENMASK(18, 14) +-#define BIT_RPT_SEL GENMASK(20, 16) +-#define BIT_GS_PWSF GENMASK(27, 0) +-#define BIT_RPT_DGAIN GENMASK(27, 16) +-#define BIT_TX_CFIR GENMASK(31, 30) +- +-#define PPG_THERMAL_A 0x1ef +-#define PPG_THERMAL_B 0x1b0 +-#define RF_THEMAL_MASK GENMASK(19, 16) +-#define PPG_2GL_TXAB 0x1d4 +-#define PPG_2GM_TXAB 0x1ee +-#define PPG_2GH_TXAB 0x1d2 +-#define PPG_2G_A_MASK GENMASK(3, 0) +-#define PPG_2G_B_MASK GENMASK(7, 4) +-#define PPG_5GL1_TXA 0x1ec +-#define PPG_5GL2_TXA 0x1e8 +-#define PPG_5GM1_TXA 0x1e4 +-#define PPG_5GM2_TXA 0x1e0 +-#define PPG_5GH1_TXA 0x1dc +-#define PPG_5GL1_TXB 0x1eb +-#define PPG_5GL2_TXB 0x1e7 +-#define PPG_5GM1_TXB 0x1e3 +-#define PPG_5GM2_TXB 0x1df +-#define PPG_5GH1_TXB 0x1db +-#define PPG_5G_MASK GENMASK(4, 0) +-#define PPG_PABIAS_2GA 0x1d6 +-#define PPG_PABIAS_2GB 0x1d5 +-#define PPG_PABIAS_5GA 0x1d8 +-#define PPG_PABIAS_5GB 0x1d7 +-#define PPG_PABIAS_MASK GENMASK(3, 0) +-#define RF_PABIAS_2G_MASK GENMASK(15, 12) +-#define RF_PABIAS_5G_MASK GENMASK(19, 16) ++#define RF_EXT_TIA_BW 0x8f ++#define BIT_PW_EXT_TIA BIT(1) ++#define RF_DIS_BYPASS_TXBB 0x9e ++#define BIT_TXBB BIT(10) ++#define BIT_TIA_BYPASS BIT(5) ++#define RF_DEBUG 0xde ++#define BIT_DE_PWR_TRIM BIT(19) ++#define BIT_DE_TX_GAIN BIT(16) ++#define BIT_DE_TRXBW BIT(2) + ++#define PPG_THERMAL_B 0x1b0 ++#define RF_THEMAL_MASK GENMASK(19, 16) ++#define PPG_2GH_TXAB 0x1d2 ++#define PPG_2G_A_MASK GENMASK(3, 0) ++#define PPG_2G_B_MASK GENMASK(7, 4) ++#define PPG_2GL_TXAB 0x1d4 ++#define PPG_PABIAS_2GB 0x1d5 ++#define PPG_PABIAS_2GA 0x1d6 ++#define PPG_PABIAS_MASK GENMASK(3, 0) ++#define PPG_PABIAS_5GB 0x1d7 ++#define PPG_PABIAS_5GA 0x1d8 ++#define PPG_5G_MASK GENMASK(4, 0) ++#define PPG_5GH1_TXB 0x1db ++#define PPG_5GH1_TXA 0x1dc ++#define PPG_5GM2_TXB 0x1df ++#define PPG_5GM2_TXA 0x1e0 ++#define PPG_5GM1_TXB 0x1e3 ++#define PPG_5GM1_TXA 0x1e4 ++#define PPG_5GL2_TXB 0x1e7 ++#define PPG_5GL2_TXA 0x1e8 ++#define PPG_5GL1_TXB 0x1eb ++#define PPG_5GL1_TXA 0x1ec ++#define PPG_2GM_TXAB 0x1ee ++#define PPG_THERMAL_A 0x1ef + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +index 3a204a7533df..f9e3d0779c59 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +@@ -13,7 +13,72 @@ static const u32 rtw8822c_mac[] = { + RTW_DECL_TABLE_PHY_COND(rtw8822c_mac, rtw_phy_cfg_mac); + + static const u32 rtw8822c_agc[] = { +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x300001FF, ++ 0x1D90, 0x300101FE, ++ 0x1D90, 0x300201FD, ++ 0x1D90, 0x300301FC, ++ 0x1D90, 0x300401FB, ++ 0x1D90, 0x300501FA, ++ 0x1D90, 0x300601F9, ++ 0x1D90, 0x300701F8, ++ 0x1D90, 0x300801F7, ++ 0x1D90, 0x300901F6, ++ 0x1D90, 0x300A01F5, ++ 0x1D90, 0x300B01F4, ++ 0x1D90, 0x300C01F3, ++ 0x1D90, 0x300D01F2, ++ 0x1D90, 0x300E01F1, ++ 0x1D90, 0x300F01F0, ++ 0x1D90, 0x301001EF, ++ 0x1D90, 0x301101EE, ++ 0x1D90, 0x301201ED, ++ 0x1D90, 0x301301EC, ++ 0x1D90, 0x301401EB, ++ 0x1D90, 0x301501EA, ++ 0x1D90, 0x301601E9, ++ 0x1D90, 0x301701E8, ++ 0x1D90, 0x301801E7, ++ 0x1D90, 0x301901E5, ++ 0x1D90, 0x301A01E4, ++ 0x1D90, 0x301B01C5, ++ 0x1D90, 0x301C01C4, ++ 0x1D90, 0x301D01C3, ++ 0x1D90, 0x301E01C2, ++ 0x1D90, 0x301F0188, ++ 0x1D90, 0x30200187, ++ 0x1D90, 0x30210186, ++ 0x1D90, 0x30220184, ++ 0x1D90, 0x30230183, ++ 0x1D90, 0x30240182, ++ 0x1D90, 0x30250181, ++ 0x1D90, 0x30260148, ++ 0x1D90, 0x30270147, ++ 0x1D90, 0x30280146, ++ 0x1D90, 0x30290144, ++ 0x1D90, 0x302A0143, ++ 0x1D90, 0x302B0142, ++ 0x1D90, 0x302C0141, ++ 0x1D90, 0x302D00C8, ++ 0x1D90, 0x302E00C7, ++ 0x1D90, 0x302F00C6, ++ 0x1D90, 0x303000C5, ++ 0x1D90, 0x303100C4, ++ 0x1D90, 0x303200C3, ++ 0x1D90, 0x30330048, ++ 0x1D90, 0x30340047, ++ 0x1D90, 0x30350046, ++ 0x1D90, 0x30360045, ++ 0x1D90, 0x30370025, ++ 0x1D90, 0x30380024, ++ 0x1D90, 0x30390023, ++ 0x1D90, 0x303A0022, ++ 0x1D90, 0x303B0021, ++ 0x1D90, 0x303C0020, ++ 0x1D90, 0x303D0003, ++ 0x1D90, 0x303E0002, ++ 0x1D90, 0x303F0001, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x300001FF, + 0x1D90, 0x300101FE, + 0x1D90, 0x300201FD, +@@ -209,7 +274,72 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x303E0002, + 0x1D90, 0x303F0001, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x3040011F, ++ 0x1D90, 0x3041011F, ++ 0x1D90, 0x3042011F, ++ 0x1D90, 0x3043011F, ++ 0x1D90, 0x3044011F, ++ 0x1D90, 0x3045011F, ++ 0x1D90, 0x3046011F, ++ 0x1D90, 0x3047011F, ++ 0x1D90, 0x3048011F, ++ 0x1D90, 0x3049011F, ++ 0x1D90, 0x304A011F, ++ 0x1D90, 0x304B011F, ++ 0x1D90, 0x304C011F, ++ 0x1D90, 0x304D011F, ++ 0x1D90, 0x304E011F, ++ 0x1D90, 0x304F00F4, ++ 0x1D90, 0x305000F3, ++ 0x1D90, 0x305100F2, ++ 0x1D90, 0x305200F1, ++ 0x1D90, 0x305300F0, ++ 0x1D90, 0x305400EF, ++ 0x1D90, 0x305500EE, ++ 0x1D90, 0x305600ED, ++ 0x1D90, 0x305700EC, ++ 0x1D90, 0x305800EB, ++ 0x1D90, 0x305900EA, ++ 0x1D90, 0x305A00E9, ++ 0x1D90, 0x305B00E8, ++ 0x1D90, 0x305C00E7, ++ 0x1D90, 0x305D00E6, ++ 0x1D90, 0x305E00E4, ++ 0x1D90, 0x305F00E3, ++ 0x1D90, 0x306000E2, ++ 0x1D90, 0x306100C4, ++ 0x1D90, 0x306200C3, ++ 0x1D90, 0x306300C2, ++ 0x1D90, 0x306400A4, ++ 0x1D90, 0x306500A3, ++ 0x1D90, 0x306600A2, ++ 0x1D90, 0x306700A1, ++ 0x1D90, 0x30680084, ++ 0x1D90, 0x30690083, ++ 0x1D90, 0x306A0082, ++ 0x1D90, 0x306B0081, ++ 0x1D90, 0x306C0080, ++ 0x1D90, 0x306D0067, ++ 0x1D90, 0x306E0066, ++ 0x1D90, 0x306F0065, ++ 0x1D90, 0x30700064, ++ 0x1D90, 0x30710063, ++ 0x1D90, 0x30720044, ++ 0x1D90, 0x30730043, ++ 0x1D90, 0x30740042, ++ 0x1D90, 0x30750041, ++ 0x1D90, 0x30760024, ++ 0x1D90, 0x30770023, ++ 0x1D90, 0x30780022, ++ 0x1D90, 0x30790021, ++ 0x1D90, 0x307A0020, ++ 0x1D90, 0x307B0004, ++ 0x1D90, 0x307C0003, ++ 0x1D90, 0x307D0002, ++ 0x1D90, 0x307E0001, ++ 0x1D90, 0x307F0000, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x304001FD, + 0x1D90, 0x304101FC, + 0x1D90, 0x304201FB, +@@ -405,137 +535,202 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x307E0001, + 0x1D90, 0x307F0000, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, +- 0x1D90, 0x308000FA, +- 0x1D90, 0x308100F9, +- 0x1D90, 0x308200F8, +- 0x1D90, 0x308300F7, +- 0x1D90, 0x308400F6, +- 0x1D90, 0x308500F5, +- 0x1D90, 0x308600F4, +- 0x1D90, 0x308700F3, +- 0x1D90, 0x308800F2, +- 0x1D90, 0x308900F1, +- 0x1D90, 0x308A00F0, +- 0x1D90, 0x308B00EF, +- 0x1D90, 0x308C00EE, +- 0x1D90, 0x308D00ED, +- 0x1D90, 0x308E00EC, +- 0x1D90, 0x308F00EB, +- 0x1D90, 0x309000EA, +- 0x1D90, 0x309100E8, +- 0x1D90, 0x309200E7, +- 0x1D90, 0x309300E6, +- 0x1D90, 0x309400E5, +- 0x1D90, 0x309500E4, +- 0x1D90, 0x309600C4, +- 0x1D90, 0x309700C3, +- 0x1D90, 0x309800C2, +- 0x1D90, 0x309900C1, +- 0x1D90, 0x309A00A3, +- 0x1D90, 0x309B00A2, +- 0x1D90, 0x309C00A1, +- 0x1D90, 0x309D0085, +- 0x1D90, 0x309E0084, +- 0x1D90, 0x309F0083, +- 0x1D90, 0x30A00082, +- 0x1D90, 0x30A10081, +- 0x1D90, 0x30A20067, +- 0x1D90, 0x30A30066, +- 0x1D90, 0x30A40065, +- 0x1D90, 0x30A50064, +- 0x1D90, 0x30A60063, +- 0x1D90, 0x30A70044, +- 0x1D90, 0x30A80043, +- 0x1D90, 0x30A90042, +- 0x1D90, 0x30AA0026, +- 0x1D90, 0x30AB0025, +- 0x1D90, 0x30AC0024, +- 0x1D90, 0x30AD0023, +- 0x1D90, 0x30AE0022, +- 0x1D90, 0x30AF0021, +- 0x1D90, 0x30B00005, +- 0x1D90, 0x30B10004, +- 0x1D90, 0x30B20003, +- 0x1D90, 0x30B30002, +- 0x1D90, 0x30B40001, +- 0x1D90, 0x30B50000, +- 0x1D90, 0x30B60000, +- 0x1D90, 0x30B70000, +- 0x1D90, 0x30B80000, +- 0x1D90, 0x30B90000, +- 0x1D90, 0x30BA0000, +- 0x1D90, 0x30BB0000, +- 0x1D90, 0x30BC0000, +- 0x1D90, 0x30BD0000, +- 0x1D90, 0x30BE0000, +- 0x1D90, 0x30BF0000, +- 0x90000016, 0x00000000, 0x40000000, 0x00000000, +- 0x1D90, 0x308000FA, +- 0x1D90, 0x308100F9, +- 0x1D90, 0x308200F8, +- 0x1D90, 0x308300F7, +- 0x1D90, 0x308400F6, +- 0x1D90, 0x308500F5, +- 0x1D90, 0x308600F4, +- 0x1D90, 0x308700F3, +- 0x1D90, 0x308800F2, +- 0x1D90, 0x308900F1, +- 0x1D90, 0x308A00F0, +- 0x1D90, 0x308B00EF, +- 0x1D90, 0x308C00EE, +- 0x1D90, 0x308D00ED, +- 0x1D90, 0x308E00EC, +- 0x1D90, 0x308F00EB, +- 0x1D90, 0x309000EA, +- 0x1D90, 0x309100E8, +- 0x1D90, 0x309200E7, +- 0x1D90, 0x309300E6, +- 0x1D90, 0x309400E5, +- 0x1D90, 0x309500E4, +- 0x1D90, 0x309600C4, +- 0x1D90, 0x309700C3, +- 0x1D90, 0x309800C2, +- 0x1D90, 0x309900C1, +- 0x1D90, 0x309A00A3, +- 0x1D90, 0x309B00A2, +- 0x1D90, 0x309C00A1, +- 0x1D90, 0x309D0085, +- 0x1D90, 0x309E0084, +- 0x1D90, 0x309F0083, +- 0x1D90, 0x30A00082, +- 0x1D90, 0x30A10081, +- 0x1D90, 0x30A20067, +- 0x1D90, 0x30A30066, +- 0x1D90, 0x30A40065, +- 0x1D90, 0x30A50064, +- 0x1D90, 0x30A60063, +- 0x1D90, 0x30A70044, +- 0x1D90, 0x30A80043, +- 0x1D90, 0x30A90042, +- 0x1D90, 0x30AA0026, +- 0x1D90, 0x30AB0025, +- 0x1D90, 0x30AC0024, +- 0x1D90, 0x30AD0023, +- 0x1D90, 0x30AE0022, +- 0x1D90, 0x30AF0021, +- 0x1D90, 0x30B00005, +- 0x1D90, 0x30B10004, +- 0x1D90, 0x30B20003, +- 0x1D90, 0x30B30002, +- 0x1D90, 0x30B40001, +- 0x1D90, 0x30B50000, +- 0x1D90, 0x30B60000, +- 0x1D90, 0x30B70000, +- 0x1D90, 0x30B80000, +- 0x1D90, 0x30B90000, +- 0x1D90, 0x30BA0000, +- 0x1D90, 0x30BB0000, +- 0x1D90, 0x30BC0000, +- 0x1D90, 0x30BD0000, +- 0x1D90, 0x30BE0000, +- 0x1D90, 0x30BF0000, +- 0xA0000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x308000FF, ++ 0x1D90, 0x308100FF, ++ 0x1D90, 0x308200FF, ++ 0x1D90, 0x308300FF, ++ 0x1D90, 0x308400FF, ++ 0x1D90, 0x308500FF, ++ 0x1D90, 0x308600FE, ++ 0x1D90, 0x308700FD, ++ 0x1D90, 0x308800FC, ++ 0x1D90, 0x308900FB, ++ 0x1D90, 0x308A00FA, ++ 0x1D90, 0x308B00F9, ++ 0x1D90, 0x308C00F8, ++ 0x1D90, 0x308D00F7, ++ 0x1D90, 0x308E00F6, ++ 0x1D90, 0x308F00F5, ++ 0x1D90, 0x309000F4, ++ 0x1D90, 0x309100F3, ++ 0x1D90, 0x309200F2, ++ 0x1D90, 0x309300F1, ++ 0x1D90, 0x309400F0, ++ 0x1D90, 0x309500EF, ++ 0x1D90, 0x309600EE, ++ 0x1D90, 0x309700ED, ++ 0x1D90, 0x309800EC, ++ 0x1D90, 0x309900EB, ++ 0x1D90, 0x309A00EA, ++ 0x1D90, 0x309B00E8, ++ 0x1D90, 0x309C00E7, ++ 0x1D90, 0x309D00E6, ++ 0x1D90, 0x309E00E5, ++ 0x1D90, 0x309F00E4, ++ 0x1D90, 0x30A000C4, ++ 0x1D90, 0x30A100C3, ++ 0x1D90, 0x30A200C2, ++ 0x1D90, 0x30A300C1, ++ 0x1D90, 0x30A400A3, ++ 0x1D90, 0x30A500A2, ++ 0x1D90, 0x30A600A1, ++ 0x1D90, 0x30A70085, ++ 0x1D90, 0x30A80084, ++ 0x1D90, 0x30A90083, ++ 0x1D90, 0x30AA0082, ++ 0x1D90, 0x30AB0081, ++ 0x1D90, 0x30AC0067, ++ 0x1D90, 0x30AD0066, ++ 0x1D90, 0x30AE0065, ++ 0x1D90, 0x30AF0064, ++ 0x1D90, 0x30B00063, ++ 0x1D90, 0x30B10044, ++ 0x1D90, 0x30B20043, ++ 0x1D90, 0x30B30042, ++ 0x1D90, 0x30B40026, ++ 0x1D90, 0x30B50025, ++ 0x1D90, 0x30B60024, ++ 0x1D90, 0x30B70023, ++ 0x1D90, 0x30B80022, ++ 0x1D90, 0x30B90021, ++ 0x1D90, 0x30BA0005, ++ 0x1D90, 0x30BB0004, ++ 0x1D90, 0x30BC0003, ++ 0x1D90, 0x30BD0002, ++ 0x1D90, 0x30BE0001, ++ 0x1D90, 0x30BF0000, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x308000FA, ++ 0x1D90, 0x308100F9, ++ 0x1D90, 0x308200F8, ++ 0x1D90, 0x308300F7, ++ 0x1D90, 0x308400F6, ++ 0x1D90, 0x308500F5, ++ 0x1D90, 0x308600F4, ++ 0x1D90, 0x308700F3, ++ 0x1D90, 0x308800F2, ++ 0x1D90, 0x308900F1, ++ 0x1D90, 0x308A00F0, ++ 0x1D90, 0x308B00EF, ++ 0x1D90, 0x308C00EE, ++ 0x1D90, 0x308D00ED, ++ 0x1D90, 0x308E00EC, ++ 0x1D90, 0x308F00EB, ++ 0x1D90, 0x309000EA, ++ 0x1D90, 0x309100E8, ++ 0x1D90, 0x309200E7, ++ 0x1D90, 0x309300E6, ++ 0x1D90, 0x309400E5, ++ 0x1D90, 0x309500E4, ++ 0x1D90, 0x309600C4, ++ 0x1D90, 0x309700C3, ++ 0x1D90, 0x309800C2, ++ 0x1D90, 0x309900C1, ++ 0x1D90, 0x309A00A3, ++ 0x1D90, 0x309B00A2, ++ 0x1D90, 0x309C00A1, ++ 0x1D90, 0x309D0085, ++ 0x1D90, 0x309E0084, ++ 0x1D90, 0x309F0083, ++ 0x1D90, 0x30A00082, ++ 0x1D90, 0x30A10081, ++ 0x1D90, 0x30A20067, ++ 0x1D90, 0x30A30066, ++ 0x1D90, 0x30A40065, ++ 0x1D90, 0x30A50064, ++ 0x1D90, 0x30A60063, ++ 0x1D90, 0x30A70044, ++ 0x1D90, 0x30A80043, ++ 0x1D90, 0x30A90042, ++ 0x1D90, 0x30AA0026, ++ 0x1D90, 0x30AB0025, ++ 0x1D90, 0x30AC0024, ++ 0x1D90, 0x30AD0023, ++ 0x1D90, 0x30AE0022, ++ 0x1D90, 0x30AF0021, ++ 0x1D90, 0x30B00005, ++ 0x1D90, 0x30B10004, ++ 0x1D90, 0x30B20003, ++ 0x1D90, 0x30B30002, ++ 0x1D90, 0x30B40001, ++ 0x1D90, 0x30B50000, ++ 0x1D90, 0x30B60000, ++ 0x1D90, 0x30B70000, ++ 0x1D90, 0x30B80000, ++ 0x1D90, 0x30B90000, ++ 0x1D90, 0x30BA0000, ++ 0x1D90, 0x30BB0000, ++ 0x1D90, 0x30BC0000, ++ 0x1D90, 0x30BD0000, ++ 0x1D90, 0x30BE0000, ++ 0x1D90, 0x30BF0000, ++ 0x90000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x308000FA, ++ 0x1D90, 0x308100F9, ++ 0x1D90, 0x308200F8, ++ 0x1D90, 0x308300F7, ++ 0x1D90, 0x308400F6, ++ 0x1D90, 0x308500F5, ++ 0x1D90, 0x308600F4, ++ 0x1D90, 0x308700F3, ++ 0x1D90, 0x308800F2, ++ 0x1D90, 0x308900F1, ++ 0x1D90, 0x308A00F0, ++ 0x1D90, 0x308B00EF, ++ 0x1D90, 0x308C00EE, ++ 0x1D90, 0x308D00ED, ++ 0x1D90, 0x308E00EC, ++ 0x1D90, 0x308F00EB, ++ 0x1D90, 0x309000EA, ++ 0x1D90, 0x309100E8, ++ 0x1D90, 0x309200E7, ++ 0x1D90, 0x309300E6, ++ 0x1D90, 0x309400E5, ++ 0x1D90, 0x309500E4, ++ 0x1D90, 0x309600C4, ++ 0x1D90, 0x309700C3, ++ 0x1D90, 0x309800C2, ++ 0x1D90, 0x309900C1, ++ 0x1D90, 0x309A00A3, ++ 0x1D90, 0x309B00A2, ++ 0x1D90, 0x309C00A1, ++ 0x1D90, 0x309D0085, ++ 0x1D90, 0x309E0084, ++ 0x1D90, 0x309F0083, ++ 0x1D90, 0x30A00082, ++ 0x1D90, 0x30A10081, ++ 0x1D90, 0x30A20067, ++ 0x1D90, 0x30A30066, ++ 0x1D90, 0x30A40065, ++ 0x1D90, 0x30A50064, ++ 0x1D90, 0x30A60063, ++ 0x1D90, 0x30A70044, ++ 0x1D90, 0x30A80043, ++ 0x1D90, 0x30A90042, ++ 0x1D90, 0x30AA0026, ++ 0x1D90, 0x30AB0025, ++ 0x1D90, 0x30AC0024, ++ 0x1D90, 0x30AD0023, ++ 0x1D90, 0x30AE0022, ++ 0x1D90, 0x30AF0021, ++ 0x1D90, 0x30B00005, ++ 0x1D90, 0x30B10004, ++ 0x1D90, 0x30B20003, ++ 0x1D90, 0x30B30002, ++ 0x1D90, 0x30B40001, ++ 0x1D90, 0x30B50000, ++ 0x1D90, 0x30B60000, ++ 0x1D90, 0x30B70000, ++ 0x1D90, 0x30B80000, ++ 0x1D90, 0x30B90000, ++ 0x1D90, 0x30BA0000, ++ 0x1D90, 0x30BB0000, ++ 0x1D90, 0x30BC0000, ++ 0x1D90, 0x30BD0000, ++ 0x1D90, 0x30BE0000, ++ 0x1D90, 0x30BF0000, ++ 0xA0000000, 0x00000000, + 0x1D90, 0x308000FF, + 0x1D90, 0x308100FF, + 0x1D90, 0x308200FF, +@@ -601,7 +796,72 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x30BE0001, + 0x1D90, 0x30BF0000, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x30C000FF, ++ 0x1D90, 0x30C100FF, ++ 0x1D90, 0x30C200FF, ++ 0x1D90, 0x30C300FF, ++ 0x1D90, 0x30C400FF, ++ 0x1D90, 0x30C500FF, ++ 0x1D90, 0x30C600FE, ++ 0x1D90, 0x30C700FD, ++ 0x1D90, 0x30C800FC, ++ 0x1D90, 0x30C900FB, ++ 0x1D90, 0x30CA00FA, ++ 0x1D90, 0x30CB00F9, ++ 0x1D90, 0x30CC00F8, ++ 0x1D90, 0x30CD00F7, ++ 0x1D90, 0x30CE00F6, ++ 0x1D90, 0x30CF00F5, ++ 0x1D90, 0x30D000F4, ++ 0x1D90, 0x30D100F3, ++ 0x1D90, 0x30D200F2, ++ 0x1D90, 0x30D300F1, ++ 0x1D90, 0x30D400F0, ++ 0x1D90, 0x30D500EF, ++ 0x1D90, 0x30D600EE, ++ 0x1D90, 0x30D700ED, ++ 0x1D90, 0x30D800EC, ++ 0x1D90, 0x30D900EB, ++ 0x1D90, 0x30DA00EA, ++ 0x1D90, 0x30DB00E8, ++ 0x1D90, 0x30DC00E7, ++ 0x1D90, 0x30DD00E6, ++ 0x1D90, 0x30DE00E5, ++ 0x1D90, 0x30DF00E4, ++ 0x1D90, 0x30E000E3, ++ 0x1D90, 0x30E100E2, ++ 0x1D90, 0x30E200A6, ++ 0x1D90, 0x30E300A5, ++ 0x1D90, 0x30E400A4, ++ 0x1D90, 0x30E500A3, ++ 0x1D90, 0x30E600A2, ++ 0x1D90, 0x30E70086, ++ 0x1D90, 0x30E80085, ++ 0x1D90, 0x30E90084, ++ 0x1D90, 0x30EA0083, ++ 0x1D90, 0x30EB0082, ++ 0x1D90, 0x30EC0067, ++ 0x1D90, 0x30ED0066, ++ 0x1D90, 0x30EE0065, ++ 0x1D90, 0x30EF0064, ++ 0x1D90, 0x30F00063, ++ 0x1D90, 0x30F10045, ++ 0x1D90, 0x30F20044, ++ 0x1D90, 0x30F30043, ++ 0x1D90, 0x30F40042, ++ 0x1D90, 0x30F50025, ++ 0x1D90, 0x30F60024, ++ 0x1D90, 0x30F70023, ++ 0x1D90, 0x30F80022, ++ 0x1D90, 0x30F90021, ++ 0x1D90, 0x30FA0005, ++ 0x1D90, 0x30FB0004, ++ 0x1D90, 0x30FC0003, ++ 0x1D90, 0x30FD0002, ++ 0x1D90, 0x30FE0001, ++ 0x1D90, 0x30FF0000, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x30C000F8, + 0x1D90, 0x30C100F7, + 0x1D90, 0x30C200F6, +@@ -797,267 +1057,397 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x30FE0001, + 0x1D90, 0x30FF0000, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x310001FF, ++ 0x1D90, 0x310101FF, ++ 0x1D90, 0x310201FF, ++ 0x1D90, 0x310301FF, ++ 0x1D90, 0x310401FE, ++ 0x1D90, 0x310501FD, ++ 0x1D90, 0x310601FC, ++ 0x1D90, 0x310701FB, ++ 0x1D90, 0x310801FA, ++ 0x1D90, 0x310901F9, ++ 0x1D90, 0x310A01F8, ++ 0x1D90, 0x310B01F7, ++ 0x1D90, 0x310C01F6, ++ 0x1D90, 0x310D01F5, ++ 0x1D90, 0x310E01F4, ++ 0x1D90, 0x310F01F3, ++ 0x1D90, 0x311001F2, ++ 0x1D90, 0x311101F1, ++ 0x1D90, 0x311201F0, ++ 0x1D90, 0x311301EF, ++ 0x1D90, 0x311401EE, ++ 0x1D90, 0x311501ED, ++ 0x1D90, 0x311601EC, ++ 0x1D90, 0x311701EB, ++ 0x1D90, 0x311801EA, ++ 0x1D90, 0x311901E9, ++ 0x1D90, 0x311A01E8, ++ 0x1D90, 0x311B01E7, ++ 0x1D90, 0x311C01E5, ++ 0x1D90, 0x311D01E4, ++ 0x1D90, 0x311E01C5, ++ 0x1D90, 0x311F01C4, ++ 0x1D90, 0x312001C3, ++ 0x1D90, 0x312101C2, ++ 0x1D90, 0x31220188, ++ 0x1D90, 0x31230187, ++ 0x1D90, 0x31240186, ++ 0x1D90, 0x31250184, ++ 0x1D90, 0x31260183, ++ 0x1D90, 0x31270182, ++ 0x1D90, 0x31280181, ++ 0x1D90, 0x31290148, ++ 0x1D90, 0x312A0147, ++ 0x1D90, 0x312B0146, ++ 0x1D90, 0x312C0144, ++ 0x1D90, 0x312D0143, ++ 0x1D90, 0x312E0142, ++ 0x1D90, 0x312F0141, ++ 0x1D90, 0x313000C8, ++ 0x1D90, 0x313100C7, ++ 0x1D90, 0x313200C6, ++ 0x1D90, 0x313300C5, ++ 0x1D90, 0x313400C4, ++ 0x1D90, 0x313500C3, ++ 0x1D90, 0x31360048, ++ 0x1D90, 0x31370047, ++ 0x1D90, 0x31380046, ++ 0x1D90, 0x31390045, ++ 0x1D90, 0x313A0025, ++ 0x1D90, 0x313B0024, ++ 0x1D90, 0x313C0023, ++ 0x1D90, 0x313D0022, ++ 0x1D90, 0x313E0021, ++ 0x1D90, 0x313F0020, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x310001FF, + 0x1D90, 0x310101FF, + 0x1D90, 0x310201FF, + 0x1D90, 0x310301FF, +- 0x1D90, 0x310401FF, +- 0x1D90, 0x310501FF, +- 0x1D90, 0x310601FF, +- 0x1D90, 0x310701FF, +- 0x1D90, 0x310801FF, +- 0x1D90, 0x310901FE, +- 0x1D90, 0x310A01FD, +- 0x1D90, 0x310B01FC, +- 0x1D90, 0x310C01FB, +- 0x1D90, 0x310D01FA, +- 0x1D90, 0x310E01F9, +- 0x1D90, 0x310F01F8, +- 0x1D90, 0x311001F7, +- 0x1D90, 0x311101F6, +- 0x1D90, 0x311201F5, +- 0x1D90, 0x311301F4, +- 0x1D90, 0x311401F3, +- 0x1D90, 0x311501F2, +- 0x1D90, 0x311601F1, +- 0x1D90, 0x311701F0, +- 0x1D90, 0x311801EF, +- 0x1D90, 0x311901EE, +- 0x1D90, 0x311A01ED, +- 0x1D90, 0x311B01EC, +- 0x1D90, 0x311C01EB, +- 0x1D90, 0x311D0192, +- 0x1D90, 0x311E0191, +- 0x1D90, 0x311F0190, +- 0x1D90, 0x3120018F, +- 0x1D90, 0x3121018E, +- 0x1D90, 0x3122018D, +- 0x1D90, 0x3123018C, +- 0x1D90, 0x3124018B, +- 0x1D90, 0x3125018A, +- 0x1D90, 0x31260189, +- 0x1D90, 0x31270188, +- 0x1D90, 0x31280187, +- 0x1D90, 0x31290186, +- 0x1D90, 0x312A0185, +- 0x1D90, 0x312B0149, +- 0x1D90, 0x312C0148, +- 0x1D90, 0x312D0147, +- 0x1D90, 0x312E0146, +- 0x1D90, 0x312F0145, +- 0x1D90, 0x31300144, +- 0x1D90, 0x31310143, +- 0x1D90, 0x31320142, +- 0x1D90, 0x31330141, +- 0x1D90, 0x31340140, +- 0x1D90, 0x313500C7, +- 0x1D90, 0x313600C6, +- 0x1D90, 0x313700C5, +- 0x1D90, 0x313800C4, +- 0x1D90, 0x313900C3, +- 0x1D90, 0x313A0088, +- 0x1D90, 0x313B0087, +- 0x1D90, 0x313C0086, +- 0x1D90, 0x313D0045, +- 0x1D90, 0x313E0044, +- 0x1D90, 0x313F0043, ++ 0x1D90, 0x310401FE, ++ 0x1D90, 0x310501FD, ++ 0x1D90, 0x310601FC, ++ 0x1D90, 0x310701FB, ++ 0x1D90, 0x310801FA, ++ 0x1D90, 0x310901F9, ++ 0x1D90, 0x310A01F8, ++ 0x1D90, 0x310B01F7, ++ 0x1D90, 0x310C01F6, ++ 0x1D90, 0x310D01F5, ++ 0x1D90, 0x310E01F4, ++ 0x1D90, 0x310F01F3, ++ 0x1D90, 0x311001F2, ++ 0x1D90, 0x311101F1, ++ 0x1D90, 0x311201F0, ++ 0x1D90, 0x311301EF, ++ 0x1D90, 0x311401EE, ++ 0x1D90, 0x311501ED, ++ 0x1D90, 0x311601EC, ++ 0x1D90, 0x311701EB, ++ 0x1D90, 0x311801EA, ++ 0x1D90, 0x311901E9, ++ 0x1D90, 0x311A01E8, ++ 0x1D90, 0x311B01E7, ++ 0x1D90, 0x311C01E5, ++ 0x1D90, 0x311D01E4, ++ 0x1D90, 0x311E01C5, ++ 0x1D90, 0x311F01C4, ++ 0x1D90, 0x312001C3, ++ 0x1D90, 0x312101C2, ++ 0x1D90, 0x31220188, ++ 0x1D90, 0x31230187, ++ 0x1D90, 0x31240186, ++ 0x1D90, 0x31250184, ++ 0x1D90, 0x31260183, ++ 0x1D90, 0x31270182, ++ 0x1D90, 0x31280181, ++ 0x1D90, 0x31290148, ++ 0x1D90, 0x312A0147, ++ 0x1D90, 0x312B0146, ++ 0x1D90, 0x312C0144, ++ 0x1D90, 0x312D0143, ++ 0x1D90, 0x312E0142, ++ 0x1D90, 0x312F0141, ++ 0x1D90, 0x313000C8, ++ 0x1D90, 0x313100C7, ++ 0x1D90, 0x313200C6, ++ 0x1D90, 0x313300C5, ++ 0x1D90, 0x313400C4, ++ 0x1D90, 0x313500C3, ++ 0x1D90, 0x31360048, ++ 0x1D90, 0x31370047, ++ 0x1D90, 0x31380046, ++ 0x1D90, 0x31390045, ++ 0x1D90, 0x313A0025, ++ 0x1D90, 0x313B0024, ++ 0x1D90, 0x313C0023, ++ 0x1D90, 0x313D0022, ++ 0x1D90, 0x313E0021, ++ 0x1D90, 0x313F0020, + 0x90000016, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x310001FF, + 0x1D90, 0x310101FF, + 0x1D90, 0x310201FF, + 0x1D90, 0x310301FF, +- 0x1D90, 0x310401FF, +- 0x1D90, 0x310501FF, +- 0x1D90, 0x310601FF, +- 0x1D90, 0x310701FF, +- 0x1D90, 0x310801FF, +- 0x1D90, 0x310901FE, +- 0x1D90, 0x310A01FD, +- 0x1D90, 0x310B01FC, +- 0x1D90, 0x310C01FB, +- 0x1D90, 0x310D01FA, +- 0x1D90, 0x310E01F9, +- 0x1D90, 0x310F01F8, +- 0x1D90, 0x311001F7, +- 0x1D90, 0x311101F6, +- 0x1D90, 0x311201F5, +- 0x1D90, 0x311301F4, +- 0x1D90, 0x311401F3, +- 0x1D90, 0x311501F2, +- 0x1D90, 0x311601F1, +- 0x1D90, 0x311701F0, +- 0x1D90, 0x311801EF, +- 0x1D90, 0x311901EE, +- 0x1D90, 0x311A01ED, +- 0x1D90, 0x311B01EC, +- 0x1D90, 0x311C01EB, +- 0x1D90, 0x311D0192, +- 0x1D90, 0x311E0191, +- 0x1D90, 0x311F0190, +- 0x1D90, 0x3120018F, +- 0x1D90, 0x3121018E, +- 0x1D90, 0x3122018D, +- 0x1D90, 0x3123018C, +- 0x1D90, 0x3124018B, +- 0x1D90, 0x3125018A, +- 0x1D90, 0x31260189, +- 0x1D90, 0x31270188, +- 0x1D90, 0x31280187, +- 0x1D90, 0x31290186, +- 0x1D90, 0x312A0185, +- 0x1D90, 0x312B0149, +- 0x1D90, 0x312C0148, +- 0x1D90, 0x312D0147, +- 0x1D90, 0x312E0146, +- 0x1D90, 0x312F0145, +- 0x1D90, 0x31300144, +- 0x1D90, 0x31310143, +- 0x1D90, 0x31320142, +- 0x1D90, 0x31330141, +- 0x1D90, 0x31340140, +- 0x1D90, 0x313500C7, +- 0x1D90, 0x313600C6, +- 0x1D90, 0x313700C5, +- 0x1D90, 0x313800C4, +- 0x1D90, 0x313900C3, +- 0x1D90, 0x313A0088, +- 0x1D90, 0x313B0087, +- 0x1D90, 0x313C0086, +- 0x1D90, 0x313D0045, +- 0x1D90, 0x313E0044, +- 0x1D90, 0x313F0043, ++ 0x1D90, 0x310401FE, ++ 0x1D90, 0x310501FD, ++ 0x1D90, 0x310601FC, ++ 0x1D90, 0x310701FB, ++ 0x1D90, 0x310801FA, ++ 0x1D90, 0x310901F9, ++ 0x1D90, 0x310A01F8, ++ 0x1D90, 0x310B01F7, ++ 0x1D90, 0x310C01F6, ++ 0x1D90, 0x310D01F5, ++ 0x1D90, 0x310E01F4, ++ 0x1D90, 0x310F01F3, ++ 0x1D90, 0x311001F2, ++ 0x1D90, 0x311101F1, ++ 0x1D90, 0x311201F0, ++ 0x1D90, 0x311301EF, ++ 0x1D90, 0x311401EE, ++ 0x1D90, 0x311501ED, ++ 0x1D90, 0x311601EC, ++ 0x1D90, 0x311701EB, ++ 0x1D90, 0x311801EA, ++ 0x1D90, 0x311901E9, ++ 0x1D90, 0x311A01E8, ++ 0x1D90, 0x311B01E7, ++ 0x1D90, 0x311C01E5, ++ 0x1D90, 0x311D01E4, ++ 0x1D90, 0x311E01C5, ++ 0x1D90, 0x311F01C4, ++ 0x1D90, 0x312001C3, ++ 0x1D90, 0x312101C2, ++ 0x1D90, 0x31220188, ++ 0x1D90, 0x31230187, ++ 0x1D90, 0x31240186, ++ 0x1D90, 0x31250184, ++ 0x1D90, 0x31260183, ++ 0x1D90, 0x31270182, ++ 0x1D90, 0x31280181, ++ 0x1D90, 0x31290148, ++ 0x1D90, 0x312A0147, ++ 0x1D90, 0x312B0146, ++ 0x1D90, 0x312C0144, ++ 0x1D90, 0x312D0143, ++ 0x1D90, 0x312E0142, ++ 0x1D90, 0x312F0141, ++ 0x1D90, 0x313000C8, ++ 0x1D90, 0x313100C7, ++ 0x1D90, 0x313200C6, ++ 0x1D90, 0x313300C5, ++ 0x1D90, 0x313400C4, ++ 0x1D90, 0x313500C3, ++ 0x1D90, 0x31360048, ++ 0x1D90, 0x31370047, ++ 0x1D90, 0x31380046, ++ 0x1D90, 0x31390045, ++ 0x1D90, 0x313A0025, ++ 0x1D90, 0x313B0024, ++ 0x1D90, 0x313C0023, ++ 0x1D90, 0x313D0022, ++ 0x1D90, 0x313E0021, ++ 0x1D90, 0x313F0020, + 0xA0000000, 0x00000000, + 0x1D90, 0x310001FF, + 0x1D90, 0x310101FF, + 0x1D90, 0x310201FF, + 0x1D90, 0x310301FF, +- 0x1D90, 0x310401FF, +- 0x1D90, 0x310501FF, +- 0x1D90, 0x310601FF, +- 0x1D90, 0x310701FF, +- 0x1D90, 0x310801FF, +- 0x1D90, 0x310901FE, +- 0x1D90, 0x310A01FD, +- 0x1D90, 0x310B01FC, +- 0x1D90, 0x310C01FB, +- 0x1D90, 0x310D01FA, +- 0x1D90, 0x310E01F9, +- 0x1D90, 0x310F01F8, +- 0x1D90, 0x311001F7, +- 0x1D90, 0x311101F6, +- 0x1D90, 0x311201F5, +- 0x1D90, 0x311301F4, +- 0x1D90, 0x311401F3, +- 0x1D90, 0x311501F2, +- 0x1D90, 0x311601F1, +- 0x1D90, 0x311701F0, +- 0x1D90, 0x311801EF, +- 0x1D90, 0x311901EE, +- 0x1D90, 0x311A01ED, +- 0x1D90, 0x311B01EC, +- 0x1D90, 0x311C01EB, +- 0x1D90, 0x311D0192, +- 0x1D90, 0x311E0191, +- 0x1D90, 0x311F0190, +- 0x1D90, 0x3120018F, +- 0x1D90, 0x3121018E, +- 0x1D90, 0x3122018D, +- 0x1D90, 0x3123018C, +- 0x1D90, 0x3124018B, +- 0x1D90, 0x3125018A, +- 0x1D90, 0x31260189, +- 0x1D90, 0x31270188, +- 0x1D90, 0x31280187, +- 0x1D90, 0x31290186, +- 0x1D90, 0x312A0185, +- 0x1D90, 0x312B0149, +- 0x1D90, 0x312C0148, +- 0x1D90, 0x312D0147, +- 0x1D90, 0x312E0146, +- 0x1D90, 0x312F0145, +- 0x1D90, 0x31300144, +- 0x1D90, 0x31310143, +- 0x1D90, 0x31320142, +- 0x1D90, 0x31330141, +- 0x1D90, 0x31340140, +- 0x1D90, 0x313500C7, +- 0x1D90, 0x313600C6, +- 0x1D90, 0x313700C5, +- 0x1D90, 0x313800C4, +- 0x1D90, 0x313900C3, +- 0x1D90, 0x313A0088, +- 0x1D90, 0x313B0087, +- 0x1D90, 0x313C0086, +- 0x1D90, 0x313D0045, +- 0x1D90, 0x313E0044, +- 0x1D90, 0x313F0043, ++ 0x1D90, 0x310401FE, ++ 0x1D90, 0x310501FD, ++ 0x1D90, 0x310601FC, ++ 0x1D90, 0x310701FB, ++ 0x1D90, 0x310801FA, ++ 0x1D90, 0x310901F9, ++ 0x1D90, 0x310A01F8, ++ 0x1D90, 0x310B01F7, ++ 0x1D90, 0x310C01F6, ++ 0x1D90, 0x310D01F5, ++ 0x1D90, 0x310E01F4, ++ 0x1D90, 0x310F01F3, ++ 0x1D90, 0x311001F2, ++ 0x1D90, 0x311101F1, ++ 0x1D90, 0x311201F0, ++ 0x1D90, 0x311301EF, ++ 0x1D90, 0x311401EE, ++ 0x1D90, 0x311501ED, ++ 0x1D90, 0x311601EC, ++ 0x1D90, 0x311701EB, ++ 0x1D90, 0x311801EA, ++ 0x1D90, 0x311901E9, ++ 0x1D90, 0x311A01E8, ++ 0x1D90, 0x311B01E7, ++ 0x1D90, 0x311C01E5, ++ 0x1D90, 0x311D01E4, ++ 0x1D90, 0x311E01C5, ++ 0x1D90, 0x311F01C4, ++ 0x1D90, 0x312001C3, ++ 0x1D90, 0x312101C2, ++ 0x1D90, 0x31220188, ++ 0x1D90, 0x31230187, ++ 0x1D90, 0x31240186, ++ 0x1D90, 0x31250184, ++ 0x1D90, 0x31260183, ++ 0x1D90, 0x31270182, ++ 0x1D90, 0x31280181, ++ 0x1D90, 0x31290148, ++ 0x1D90, 0x312A0147, ++ 0x1D90, 0x312B0146, ++ 0x1D90, 0x312C0144, ++ 0x1D90, 0x312D0143, ++ 0x1D90, 0x312E0142, ++ 0x1D90, 0x312F0141, ++ 0x1D90, 0x313000C8, ++ 0x1D90, 0x313100C7, ++ 0x1D90, 0x313200C6, ++ 0x1D90, 0x313300C5, ++ 0x1D90, 0x313400C4, ++ 0x1D90, 0x313500C3, ++ 0x1D90, 0x31360048, ++ 0x1D90, 0x31370047, ++ 0x1D90, 0x31380046, ++ 0x1D90, 0x31390045, ++ 0x1D90, 0x313A0025, ++ 0x1D90, 0x313B0024, ++ 0x1D90, 0x313C0023, ++ 0x1D90, 0x313D0022, ++ 0x1D90, 0x313E0021, ++ 0x1D90, 0x313F0020, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x314001FF, + 0x1D90, 0x314101FF, + 0x1D90, 0x314201FF, + 0x1D90, 0x314301FF, + 0x1D90, 0x314401FF, + 0x1D90, 0x314501FF, +- 0x1D90, 0x314601FF, +- 0x1D90, 0x314701FE, +- 0x1D90, 0x314801FD, +- 0x1D90, 0x314901FC, +- 0x1D90, 0x314A01FB, +- 0x1D90, 0x314B01FA, +- 0x1D90, 0x314C01F9, +- 0x1D90, 0x314D01F8, +- 0x1D90, 0x314E01F7, +- 0x1D90, 0x314F01F6, +- 0x1D90, 0x315001F5, +- 0x1D90, 0x315101F4, +- 0x1D90, 0x315201F3, +- 0x1D90, 0x315301F2, +- 0x1D90, 0x315401F1, +- 0x1D90, 0x315501F0, +- 0x1D90, 0x315601EF, +- 0x1D90, 0x315701EE, +- 0x1D90, 0x315801ED, +- 0x1D90, 0x315901EC, +- 0x1D90, 0x315A01EB, +- 0x1D90, 0x315B01EA, +- 0x1D90, 0x315C01E9, +- 0x1D90, 0x315D018F, +- 0x1D90, 0x315E018E, +- 0x1D90, 0x315F018D, +- 0x1D90, 0x3160018C, +- 0x1D90, 0x3161018B, +- 0x1D90, 0x3162018A, +- 0x1D90, 0x31630189, +- 0x1D90, 0x31640188, +- 0x1D90, 0x31650187, +- 0x1D90, 0x31660186, +- 0x1D90, 0x31670185, +- 0x1D90, 0x31680184, +- 0x1D90, 0x31690183, +- 0x1D90, 0x316A0182, +- 0x1D90, 0x316B0149, +- 0x1D90, 0x316C0148, +- 0x1D90, 0x316D0147, +- 0x1D90, 0x316E0146, +- 0x1D90, 0x316F0145, +- 0x1D90, 0x31700144, +- 0x1D90, 0x31710143, +- 0x1D90, 0x31720142, +- 0x1D90, 0x31730141, +- 0x1D90, 0x31740140, +- 0x1D90, 0x317500C7, +- 0x1D90, 0x317600C6, +- 0x1D90, 0x317700C5, +- 0x1D90, 0x317800C4, +- 0x1D90, 0x317900C3, +- 0x1D90, 0x317A0088, +- 0x1D90, 0x317B0087, +- 0x1D90, 0x317C0086, +- 0x1D90, 0x317D0045, +- 0x1D90, 0x317E0044, +- 0x1D90, 0x317F0043, ++ 0x1D90, 0x314601FE, ++ 0x1D90, 0x314701FD, ++ 0x1D90, 0x314801FC, ++ 0x1D90, 0x314901FB, ++ 0x1D90, 0x314A01FA, ++ 0x1D90, 0x314B01F9, ++ 0x1D90, 0x314C01F8, ++ 0x1D90, 0x314D01F7, ++ 0x1D90, 0x314E01F6, ++ 0x1D90, 0x314F01F5, ++ 0x1D90, 0x315001F4, ++ 0x1D90, 0x315101F3, ++ 0x1D90, 0x315201F2, ++ 0x1D90, 0x315301F1, ++ 0x1D90, 0x315401F0, ++ 0x1D90, 0x315501EF, ++ 0x1D90, 0x315601EE, ++ 0x1D90, 0x315701ED, ++ 0x1D90, 0x315801EC, ++ 0x1D90, 0x315901EB, ++ 0x1D90, 0x315A01EA, ++ 0x1D90, 0x315B01E9, ++ 0x1D90, 0x315C01E7, ++ 0x1D90, 0x315D01E6, ++ 0x1D90, 0x315E01E5, ++ 0x1D90, 0x315F01E4, ++ 0x1D90, 0x316001A8, ++ 0x1D90, 0x316101A7, ++ 0x1D90, 0x316201A6, ++ 0x1D90, 0x316301A5, ++ 0x1D90, 0x31640185, ++ 0x1D90, 0x31650184, ++ 0x1D90, 0x31660183, ++ 0x1D90, 0x31670182, ++ 0x1D90, 0x31680149, ++ 0x1D90, 0x31690148, ++ 0x1D90, 0x316A0147, ++ 0x1D90, 0x316B0145, ++ 0x1D90, 0x316C0144, ++ 0x1D90, 0x316D0143, ++ 0x1D90, 0x316E0142, ++ 0x1D90, 0x316F00E6, ++ 0x1D90, 0x317000E5, ++ 0x1D90, 0x317100C9, ++ 0x1D90, 0x317200C8, ++ 0x1D90, 0x317300C7, ++ 0x1D90, 0x317400C6, ++ 0x1D90, 0x317500C5, ++ 0x1D90, 0x317600C4, ++ 0x1D90, 0x317700C3, ++ 0x1D90, 0x31780088, ++ 0x1D90, 0x31790087, ++ 0x1D90, 0x317A0086, ++ 0x1D90, 0x317B0085, ++ 0x1D90, 0x317C0026, ++ 0x1D90, 0x317D0025, ++ 0x1D90, 0x317E0024, ++ 0x1D90, 0x317F0023, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x314001FF, ++ 0x1D90, 0x314101FF, ++ 0x1D90, 0x314201FF, ++ 0x1D90, 0x314301FF, ++ 0x1D90, 0x314401FF, ++ 0x1D90, 0x314501FF, ++ 0x1D90, 0x314601FE, ++ 0x1D90, 0x314701FD, ++ 0x1D90, 0x314801FC, ++ 0x1D90, 0x314901FB, ++ 0x1D90, 0x314A01FA, ++ 0x1D90, 0x314B01F9, ++ 0x1D90, 0x314C01F8, ++ 0x1D90, 0x314D01F7, ++ 0x1D90, 0x314E01F6, ++ 0x1D90, 0x314F01F5, ++ 0x1D90, 0x315001F4, ++ 0x1D90, 0x315101F3, ++ 0x1D90, 0x315201F2, ++ 0x1D90, 0x315301F1, ++ 0x1D90, 0x315401F0, ++ 0x1D90, 0x315501EF, ++ 0x1D90, 0x315601EE, ++ 0x1D90, 0x315701ED, ++ 0x1D90, 0x315801EC, ++ 0x1D90, 0x315901EB, ++ 0x1D90, 0x315A01EA, ++ 0x1D90, 0x315B01E9, ++ 0x1D90, 0x315C01E7, ++ 0x1D90, 0x315D01E6, ++ 0x1D90, 0x315E01E5, ++ 0x1D90, 0x315F01E4, ++ 0x1D90, 0x316001A8, ++ 0x1D90, 0x316101A7, ++ 0x1D90, 0x316201A6, ++ 0x1D90, 0x316301A5, ++ 0x1D90, 0x31640185, ++ 0x1D90, 0x31650184, ++ 0x1D90, 0x31660183, ++ 0x1D90, 0x31670182, ++ 0x1D90, 0x31680149, ++ 0x1D90, 0x31690148, ++ 0x1D90, 0x316A0147, ++ 0x1D90, 0x316B0145, ++ 0x1D90, 0x316C0144, ++ 0x1D90, 0x316D0143, ++ 0x1D90, 0x316E0142, ++ 0x1D90, 0x316F00E6, ++ 0x1D90, 0x317000E5, ++ 0x1D90, 0x317100C9, ++ 0x1D90, 0x317200C8, ++ 0x1D90, 0x317300C7, ++ 0x1D90, 0x317400C6, ++ 0x1D90, 0x317500C5, ++ 0x1D90, 0x317600C4, ++ 0x1D90, 0x317700C3, ++ 0x1D90, 0x31780088, ++ 0x1D90, 0x31790087, ++ 0x1D90, 0x317A0086, ++ 0x1D90, 0x317B0085, ++ 0x1D90, 0x317C0026, ++ 0x1D90, 0x317D0025, ++ 0x1D90, 0x317E0024, ++ 0x1D90, 0x317F0023, + 0x90000016, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x314001FF, + 0x1D90, 0x314101FF, +@@ -1065,64 +1455,64 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x314301FF, + 0x1D90, 0x314401FF, + 0x1D90, 0x314501FF, +- 0x1D90, 0x314601FF, +- 0x1D90, 0x314701FE, +- 0x1D90, 0x314801FD, +- 0x1D90, 0x314901FC, +- 0x1D90, 0x314A01FB, +- 0x1D90, 0x314B01FA, +- 0x1D90, 0x314C01F9, +- 0x1D90, 0x314D01F8, +- 0x1D90, 0x314E01F7, +- 0x1D90, 0x314F01F6, +- 0x1D90, 0x315001F5, +- 0x1D90, 0x315101F4, +- 0x1D90, 0x315201F3, +- 0x1D90, 0x315301F2, +- 0x1D90, 0x315401F1, +- 0x1D90, 0x315501F0, +- 0x1D90, 0x315601EF, +- 0x1D90, 0x315701EE, +- 0x1D90, 0x315801ED, +- 0x1D90, 0x315901EC, +- 0x1D90, 0x315A01EB, +- 0x1D90, 0x315B01EA, +- 0x1D90, 0x315C01E9, +- 0x1D90, 0x315D018F, +- 0x1D90, 0x315E018E, +- 0x1D90, 0x315F018D, +- 0x1D90, 0x3160018C, +- 0x1D90, 0x3161018B, +- 0x1D90, 0x3162018A, +- 0x1D90, 0x31630189, +- 0x1D90, 0x31640188, +- 0x1D90, 0x31650187, +- 0x1D90, 0x31660186, +- 0x1D90, 0x31670185, +- 0x1D90, 0x31680184, +- 0x1D90, 0x31690183, +- 0x1D90, 0x316A0182, +- 0x1D90, 0x316B0149, +- 0x1D90, 0x316C0148, +- 0x1D90, 0x316D0147, +- 0x1D90, 0x316E0146, +- 0x1D90, 0x316F0145, +- 0x1D90, 0x31700144, +- 0x1D90, 0x31710143, +- 0x1D90, 0x31720142, +- 0x1D90, 0x31730141, +- 0x1D90, 0x31740140, +- 0x1D90, 0x317500C7, +- 0x1D90, 0x317600C6, +- 0x1D90, 0x317700C5, +- 0x1D90, 0x317800C4, +- 0x1D90, 0x317900C3, +- 0x1D90, 0x317A0088, +- 0x1D90, 0x317B0087, +- 0x1D90, 0x317C0086, +- 0x1D90, 0x317D0045, +- 0x1D90, 0x317E0044, +- 0x1D90, 0x317F0043, ++ 0x1D90, 0x314601FE, ++ 0x1D90, 0x314701FD, ++ 0x1D90, 0x314801FC, ++ 0x1D90, 0x314901FB, ++ 0x1D90, 0x314A01FA, ++ 0x1D90, 0x314B01F9, ++ 0x1D90, 0x314C01F8, ++ 0x1D90, 0x314D01F7, ++ 0x1D90, 0x314E01F6, ++ 0x1D90, 0x314F01F5, ++ 0x1D90, 0x315001F4, ++ 0x1D90, 0x315101F3, ++ 0x1D90, 0x315201F2, ++ 0x1D90, 0x315301F1, ++ 0x1D90, 0x315401F0, ++ 0x1D90, 0x315501EF, ++ 0x1D90, 0x315601EE, ++ 0x1D90, 0x315701ED, ++ 0x1D90, 0x315801EC, ++ 0x1D90, 0x315901EB, ++ 0x1D90, 0x315A01EA, ++ 0x1D90, 0x315B01E9, ++ 0x1D90, 0x315C01E7, ++ 0x1D90, 0x315D01E6, ++ 0x1D90, 0x315E01E5, ++ 0x1D90, 0x315F01E4, ++ 0x1D90, 0x316001A8, ++ 0x1D90, 0x316101A7, ++ 0x1D90, 0x316201A6, ++ 0x1D90, 0x316301A5, ++ 0x1D90, 0x31640185, ++ 0x1D90, 0x31650184, ++ 0x1D90, 0x31660183, ++ 0x1D90, 0x31670182, ++ 0x1D90, 0x31680149, ++ 0x1D90, 0x31690148, ++ 0x1D90, 0x316A0147, ++ 0x1D90, 0x316B0145, ++ 0x1D90, 0x316C0144, ++ 0x1D90, 0x316D0143, ++ 0x1D90, 0x316E0142, ++ 0x1D90, 0x316F00E6, ++ 0x1D90, 0x317000E5, ++ 0x1D90, 0x317100C9, ++ 0x1D90, 0x317200C8, ++ 0x1D90, 0x317300C7, ++ 0x1D90, 0x317400C6, ++ 0x1D90, 0x317500C5, ++ 0x1D90, 0x317600C4, ++ 0x1D90, 0x317700C3, ++ 0x1D90, 0x31780088, ++ 0x1D90, 0x31790087, ++ 0x1D90, 0x317A0086, ++ 0x1D90, 0x317B0085, ++ 0x1D90, 0x317C0026, ++ 0x1D90, 0x317D0025, ++ 0x1D90, 0x317E0024, ++ 0x1D90, 0x317F0023, + 0xA0000000, 0x00000000, + 0x1D90, 0x314001FF, + 0x1D90, 0x314101FF, +@@ -1130,66 +1520,131 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x314301FF, + 0x1D90, 0x314401FF, + 0x1D90, 0x314501FF, +- 0x1D90, 0x314601FF, +- 0x1D90, 0x314701FE, +- 0x1D90, 0x314801FD, +- 0x1D90, 0x314901FC, +- 0x1D90, 0x314A01FB, +- 0x1D90, 0x314B01FA, +- 0x1D90, 0x314C01F9, +- 0x1D90, 0x314D01F8, +- 0x1D90, 0x314E01F7, +- 0x1D90, 0x314F01F6, +- 0x1D90, 0x315001F5, +- 0x1D90, 0x315101F4, +- 0x1D90, 0x315201F3, +- 0x1D90, 0x315301F2, +- 0x1D90, 0x315401F1, +- 0x1D90, 0x315501F0, +- 0x1D90, 0x315601EF, +- 0x1D90, 0x315701EE, +- 0x1D90, 0x315801ED, +- 0x1D90, 0x315901EC, +- 0x1D90, 0x315A01EB, +- 0x1D90, 0x315B01EA, +- 0x1D90, 0x315C01E9, +- 0x1D90, 0x315D018F, +- 0x1D90, 0x315E018E, +- 0x1D90, 0x315F018D, +- 0x1D90, 0x3160018C, +- 0x1D90, 0x3161018B, +- 0x1D90, 0x3162018A, +- 0x1D90, 0x31630189, +- 0x1D90, 0x31640188, +- 0x1D90, 0x31650187, +- 0x1D90, 0x31660186, +- 0x1D90, 0x31670185, +- 0x1D90, 0x31680184, +- 0x1D90, 0x31690183, +- 0x1D90, 0x316A0182, +- 0x1D90, 0x316B0149, +- 0x1D90, 0x316C0148, +- 0x1D90, 0x316D0147, +- 0x1D90, 0x316E0146, +- 0x1D90, 0x316F0145, +- 0x1D90, 0x31700144, +- 0x1D90, 0x31710143, +- 0x1D90, 0x31720142, +- 0x1D90, 0x31730141, +- 0x1D90, 0x31740140, +- 0x1D90, 0x317500C7, +- 0x1D90, 0x317600C6, +- 0x1D90, 0x317700C5, +- 0x1D90, 0x317800C4, +- 0x1D90, 0x317900C3, +- 0x1D90, 0x317A0088, +- 0x1D90, 0x317B0087, +- 0x1D90, 0x317C0086, +- 0x1D90, 0x317D0045, +- 0x1D90, 0x317E0044, +- 0x1D90, 0x317F0043, ++ 0x1D90, 0x314601FE, ++ 0x1D90, 0x314701FD, ++ 0x1D90, 0x314801FC, ++ 0x1D90, 0x314901FB, ++ 0x1D90, 0x314A01FA, ++ 0x1D90, 0x314B01F9, ++ 0x1D90, 0x314C01F8, ++ 0x1D90, 0x314D01F7, ++ 0x1D90, 0x314E01F6, ++ 0x1D90, 0x314F01F5, ++ 0x1D90, 0x315001F4, ++ 0x1D90, 0x315101F3, ++ 0x1D90, 0x315201F2, ++ 0x1D90, 0x315301F1, ++ 0x1D90, 0x315401F0, ++ 0x1D90, 0x315501EF, ++ 0x1D90, 0x315601EE, ++ 0x1D90, 0x315701ED, ++ 0x1D90, 0x315801EC, ++ 0x1D90, 0x315901EB, ++ 0x1D90, 0x315A01EA, ++ 0x1D90, 0x315B01E9, ++ 0x1D90, 0x315C01E7, ++ 0x1D90, 0x315D01E6, ++ 0x1D90, 0x315E01E5, ++ 0x1D90, 0x315F01E4, ++ 0x1D90, 0x316001A8, ++ 0x1D90, 0x316101A7, ++ 0x1D90, 0x316201A6, ++ 0x1D90, 0x316301A5, ++ 0x1D90, 0x31640185, ++ 0x1D90, 0x31650184, ++ 0x1D90, 0x31660183, ++ 0x1D90, 0x31670182, ++ 0x1D90, 0x31680149, ++ 0x1D90, 0x31690148, ++ 0x1D90, 0x316A0147, ++ 0x1D90, 0x316B0145, ++ 0x1D90, 0x316C0144, ++ 0x1D90, 0x316D0143, ++ 0x1D90, 0x316E0142, ++ 0x1D90, 0x316F00E6, ++ 0x1D90, 0x317000E5, ++ 0x1D90, 0x317100C9, ++ 0x1D90, 0x317200C8, ++ 0x1D90, 0x317300C7, ++ 0x1D90, 0x317400C6, ++ 0x1D90, 0x317500C5, ++ 0x1D90, 0x317600C4, ++ 0x1D90, 0x317700C3, ++ 0x1D90, 0x31780088, ++ 0x1D90, 0x31790087, ++ 0x1D90, 0x317A0086, ++ 0x1D90, 0x317B0085, ++ 0x1D90, 0x317C0026, ++ 0x1D90, 0x317D0025, ++ 0x1D90, 0x317E0024, ++ 0x1D90, 0x317F0023, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D90, 0x318001FE, ++ 0x1D90, 0x318101FD, ++ 0x1D90, 0x318201FC, ++ 0x1D90, 0x318301FB, ++ 0x1D90, 0x318401FA, ++ 0x1D90, 0x318501F9, ++ 0x1D90, 0x318601F8, ++ 0x1D90, 0x318701F7, ++ 0x1D90, 0x318801F6, ++ 0x1D90, 0x318901F5, ++ 0x1D90, 0x318A01F4, ++ 0x1D90, 0x318B01F3, ++ 0x1D90, 0x318C01F2, ++ 0x1D90, 0x318D01F1, ++ 0x1D90, 0x318E01F0, ++ 0x1D90, 0x318F01EF, ++ 0x1D90, 0x319001EE, ++ 0x1D90, 0x319101ED, ++ 0x1D90, 0x319201EC, ++ 0x1D90, 0x319301EB, ++ 0x1D90, 0x319401EA, ++ 0x1D90, 0x319501E9, ++ 0x1D90, 0x319601E7, ++ 0x1D90, 0x319701E6, ++ 0x1D90, 0x319801E5, ++ 0x1D90, 0x319901E4, ++ 0x1D90, 0x319A01A8, ++ 0x1D90, 0x319B01A7, ++ 0x1D90, 0x319C01A6, ++ 0x1D90, 0x319D01A5, ++ 0x1D90, 0x319E0185, ++ 0x1D90, 0x319F0184, ++ 0x1D90, 0x31A00183, ++ 0x1D90, 0x31A10182, ++ 0x1D90, 0x31A20149, ++ 0x1D90, 0x31A30148, ++ 0x1D90, 0x31A40147, ++ 0x1D90, 0x31A50145, ++ 0x1D90, 0x31A60144, ++ 0x1D90, 0x31A70143, ++ 0x1D90, 0x31A80142, ++ 0x1D90, 0x31A900E6, ++ 0x1D90, 0x31AA00E5, ++ 0x1D90, 0x31AB00C9, ++ 0x1D90, 0x31AC00C8, ++ 0x1D90, 0x31AD00C7, ++ 0x1D90, 0x31AE00C6, ++ 0x1D90, 0x31AF00C5, ++ 0x1D90, 0x31B000C4, ++ 0x1D90, 0x31B100C3, ++ 0x1D90, 0x31B20088, ++ 0x1D90, 0x31B30087, ++ 0x1D90, 0x31B40086, ++ 0x1D90, 0x31B50085, ++ 0x1D90, 0x31B60026, ++ 0x1D90, 0x31B70025, ++ 0x1D90, 0x31B80024, ++ 0x1D90, 0x31B90023, ++ 0x1D90, 0x31BA0022, ++ 0x1D90, 0x31BB0021, ++ 0x1D90, 0x31BC0020, ++ 0x1D90, 0x31BD0003, ++ 0x1D90, 0x31BE0002, ++ 0x1D90, 0x31BF0001, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D90, 0x318001FE, + 0x1D90, 0x318101FD, + 0x1D90, 0x318201FC, +@@ -1385,7 +1840,10 @@ static const u32 rtw8822c_agc[] = { + 0x1D90, 0x31BE0002, + 0x1D90, 0x31BF0001, + 0xB0000000, 0x00000000, +- 0x80000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1D70, 0x22222222, ++ 0x1D70, 0x20202020, ++ 0x90000015, 0x00000000, 0x40000000, 0x00000000, + 0x1D70, 0x22222222, + 0x1D70, 0x20202020, + 0x90000016, 0x00000000, 0x40000000, 0x00000000, +@@ -1793,7 +2251,9 @@ static const u32 rtw8822c_bb[] = { + 0x1828, 0x000004FD, + 0x182C, 0x00000000, + 0x1834, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1838, 0x20000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x1838, 0x20100000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x1838, 0x20100000, +@@ -1801,11 +2261,17 @@ static const u32 rtw8822c_bb[] = { + 0x1838, 0x20100000, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x1838, 0x20100000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1838, 0x20100000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x1838, 0x20100000, + 0xA0000000, 0x00000000, + 0x1838, 0x20000000, + 0xB0000000, 0x00000000, + 0x183C, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1840, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x1840, 0x00002300, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x1840, 0x00002300, +@@ -1813,6 +2279,10 @@ static const u32 rtw8822c_bb[] = { + 0x1840, 0x00002300, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x1840, 0x00002300, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1840, 0x00002300, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x1840, 0x00002300, + 0xA0000000, 0x00000000, + 0x1840, 0x00000000, + 0xB0000000, 0x00000000, +@@ -1826,7 +2296,9 @@ static const u32 rtw8822c_bb[] = { + 0x1860, 0xF0040FF8, + 0x1864, 0x7F000000, + 0x1868, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x186C, 0x0000FF00, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x186C, 0x0000FF02, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x186C, 0x0000FF02, +@@ -1834,6 +2306,10 @@ static const u32 rtw8822c_bb[] = { + 0x186C, 0x0000FF02, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x186C, 0x0000FF02, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x186C, 0x0000FF02, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x186C, 0x0000FF02, + 0xA0000000, 0x00000000, + 0x186C, 0x0000FF00, + 0xB0000000, 0x00000000, +@@ -1842,7 +2318,9 @@ static const u32 rtw8822c_bb[] = { + 0x1878, 0x00000000, + 0x187C, 0x00000000, + 0x1880, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1884, 0x02B00000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x1884, 0x03B00000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x1884, 0x03B00000, +@@ -1850,6 +2328,10 @@ static const u32 rtw8822c_bb[] = { + 0x1884, 0x03B00000, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x1884, 0x03B00000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1884, 0x03B00000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x1884, 0x03B00000, + 0xA0000000, 0x00000000, + 0x1884, 0x02B00000, + 0xB0000000, 0x00000000, +@@ -1982,7 +2464,10 @@ static const u32 rtw8822c_bb[] = { + 0x1C84, 0x245120D4, + 0x1C88, 0xC8400483, + 0x1C8C, 0x40005A20, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x1C94, 0x00000000, ++ 0x1C98, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x1C94, 0x00000B0E, + 0x1C98, 0x00450000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -1994,6 +2479,12 @@ static const u32 rtw8822c_bb[] = { + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x1C94, 0x00000B0E, + 0x1C98, 0x00450000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x1C94, 0x00000B0E, ++ 0x1C98, 0x00450000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x1C94, 0x00000B0E, ++ 0x1C98, 0x00450000, + 0xA0000000, 0x00000000, + 0x1C94, 0x00000000, + 0x1C98, 0x00000000, +@@ -2330,7 +2821,9 @@ static const u32 rtw8822c_bb[] = { + 0x4128, 0x000004FD, + 0x412C, 0x00000000, + 0x4134, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x4138, 0x20000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x4138, 0x20100000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x4138, 0x20100000, +@@ -2338,12 +2831,18 @@ static const u32 rtw8822c_bb[] = { + 0x4138, 0x20100000, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x4138, 0x20100000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x4138, 0x20100000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x4138, 0x20100000, + 0xA0000000, 0x00000000, + 0x4138, 0x20000000, + 0xB0000000, 0x00000000, + 0x413C, 0x00000000, + 0x4140, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x4144, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x4144, 0x00002030, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x4144, 0x00002030, +@@ -2351,6 +2850,10 @@ static const u32 rtw8822c_bb[] = { + 0x4144, 0x00002030, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x4144, 0x00002030, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x4144, 0x00002030, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x4144, 0x00002030, + 0xA0000000, 0x00000000, + 0x4144, 0x00000000, + 0xB0000000, 0x00000000, +@@ -2363,7 +2866,9 @@ static const u32 rtw8822c_bb[] = { + 0x4160, 0xF0040FF8, + 0x4164, 0x7F000000, + 0x4168, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x416C, 0x00008000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x416C, 0x00008002, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x416C, 0x00008002, +@@ -2371,6 +2876,10 @@ static const u32 rtw8822c_bb[] = { + 0x416C, 0x00008002, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x416C, 0x00008002, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x416C, 0x00008002, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x416C, 0x00008002, + 0xA0000000, 0x00000000, + 0x416C, 0x00008000, + 0xB0000000, 0x00000000, +@@ -2379,7 +2888,9 @@ static const u32 rtw8822c_bb[] = { + 0x4178, 0x00000000, + 0x417C, 0x00000000, + 0x4180, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x83000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x4184, 0x02B00000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x4184, 0x03B00000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x4184, 0x03B00000, +@@ -2387,6 +2898,10 @@ static const u32 rtw8822c_bb[] = { + 0x4184, 0x03B00000, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x4184, 0x03B00000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x4184, 0x03B00000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x4184, 0x03B00000, + 0xA0000000, 0x00000000, + 0x4184, 0x02B00000, + 0xB0000000, 0x00000000, +@@ -2843,7 +3358,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x018, 0x00013124, + 0x093, 0x0008483F, + 0x0DE, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, +@@ -2861,6 +3380,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x08E, 0x000A5540, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -2875,17 +3396,39 @@ static const u32 rtw8822c_rf_a[] = { + 0x08E, 0x000A5540, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0xA0000000, 0x00000000, + 0x08E, 0x000A5540, + 0xB0000000, 0x00000000, + 0x081, 0x0000FC01, + 0x081, 0x0002FC01, + 0x081, 0x0003FC01, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, +@@ -2903,6 +3446,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x085, 0x0006A06C, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -2917,14 +3462,50 @@ static const u32 rtw8822c_rf_a[] = { + 0x085, 0x0006A06C, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x085, 0x0006A06C, + 0xA0000000, 0x00000000, + 0x085, 0x0006A06C, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000003F, ++ 0x0EE, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000003F, ++ 0x0EE, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, +@@ -3005,6 +3586,15 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, +@@ -3068,6 +3658,15 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, +@@ -3086,6 +3685,78 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, +@@ -3096,7 +3767,59 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x0000003F, + 0x0EE, 0x00000000, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -3330,6 +4053,32 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, +@@ -3512,6 +4261,32 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, +@@ -3564,6 +4339,214 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, +@@ -3593,7 +4576,57 @@ static const u32 rtw8822c_rf_a[] = { + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -3818,6 +4851,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, +@@ -3993,6 +5051,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, +@@ -4043,6 +5126,206 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773E8, +@@ -4071,17 +5354,17 @@ static const u32 rtw8822c_rf_a[] = { + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000002E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000002D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000002C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000002B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, +@@ -4096,17 +5379,17 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000002E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000002D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000002C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000002B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, +@@ -4121,7 +5404,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -4146,7 +5429,57 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -4296,6 +5629,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, +@@ -4471,6 +5829,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, +@@ -4521,6 +5904,206 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773E8, +@@ -4549,17 +6132,17 @@ static const u32 rtw8822c_rf_a[] = { + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000003E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000003C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +@@ -4574,17 +6157,17 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000003E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000003C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +@@ -4599,7 +6182,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4624,7 +6207,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4649,7 +6232,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4674,7 +6257,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4699,7 +6282,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4709,11 +6292,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -4724,7 +6307,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4734,11 +6317,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -4749,7 +6332,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4759,11 +6342,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -4774,7 +6357,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4799,7 +6382,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4809,11 +6392,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -4824,7 +6407,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4849,7 +6432,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4859,11 +6442,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -4874,7 +6457,82 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -4949,6 +6607,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, +@@ -4999,6 +6682,206 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773E8, +@@ -5027,7 +6910,57 @@ static const u32 rtw8822c_rf_a[] = { + 0xB0000000, 0x00000000, + 0x033, 0x00000033, + 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -5252,6 +7185,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, +@@ -5427,7 +7385,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -5437,11 +7395,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -5452,7 +7410,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -5477,21 +7435,21 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, +- 0x03F, 0x000773E8, ++ 0x03F, 0x000773C0, + 0x033, 0x0000004E, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, +- 0x03F, 0x00000380, ++ 0x03F, 0x000773E8, + 0x033, 0x0000004C, +- 0x03F, 0x000FF380, ++ 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x00000300, ++ 0x03F, 0x00000287, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -5502,127 +7460,402 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000043, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000005F, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000005E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000005D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000005C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000005B, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000005A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000059, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000058, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000057, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000056, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000055, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000054, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000005F, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000005E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000005D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000005C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000005B, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000005A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000059, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000058, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000057, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000056, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000055, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000054, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000005F, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000005E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000005D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000005C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000005B, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000005A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000059, +- 0x03F, 0x00000280, +- 0x033, 0x00000058, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000057, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000056, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000055, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000054, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000005F, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000005E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000005D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000005C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000005B, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000005A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000059, +- 0x03F, 0x00000280, +- 0x033, 0x00000058, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000057, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000056, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000055, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000054, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000005F, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000005E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000005D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000005C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000005B, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000005A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000059, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000058, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000057, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0xA0000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000043, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, +@@ -5730,6 +7963,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, +@@ -5905,6 +8163,31 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, +@@ -5955,17 +8238,117 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, + 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, + 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, +- 0x03F, 0x00000380, ++ 0x03F, 0x000773E8, + 0x033, 0x0000005C, +- 0x03F, 0x000FF380, ++ 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, +- 0x03F, 0x00000300, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, +@@ -5980,96 +8363,220 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000053, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0xA0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0xB0000000, 0x00000000, +- 0x08A, 0x000E7DE3, +- 0x08B, 0x0008FE00, +- 0x0EE, 0x00000008, +- 0x033, 0x00000000, +- 0x03F, 0x00000023, +- 0x033, 0x00000001, +- 0x03F, 0x00000023, +- 0x0EE, 0x00000000, +- 0x0EF, 0x00004000, +- 0x033, 0x00000000, +- 0x03F, 0x0000000F, +- 0x033, 0x00000002, +- 0x03F, 0x00000000, +- 0x0EF, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00020000, +- 0x033, 0x00000000, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000001, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000002, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000003, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000004, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000005, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000006, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000007, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, +- 0x033, 0x00000008, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, +- 0x033, 0x00000009, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000000A, +- 0x03E, 0x00000F02, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0xA0000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000053, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0xA0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x08A, 0x000E7DE3, ++ 0x08B, 0x0008FE00, ++ 0x0EE, 0x00000008, ++ 0x033, 0x00000000, ++ 0x03F, 0x00000023, ++ 0x033, 0x00000001, ++ 0x03F, 0x00000023, ++ 0x0EE, 0x00000000, ++ 0x0EF, 0x00004000, ++ 0x033, 0x00000000, ++ 0x03F, 0x0000000F, ++ 0x033, 0x00000002, ++ 0x03F, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, +@@ -6085,9 +8592,9 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03F, 0x0002C010, + 0x033, 0x00000010, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, +@@ -6111,7 +8618,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, +@@ -6135,7 +8642,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, +@@ -6159,7 +8666,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, +@@ -6183,10 +8690,10 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, +@@ -6208,10 +8715,10 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03F, 0x0002C010, + 0x033, 0x00000008, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, +@@ -6232,9 +8739,9 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03F, 0x0002C010, + 0x033, 0x00000010, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, +@@ -6258,7 +8765,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, +@@ -6282,7 +8789,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, +@@ -6306,7 +8813,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, +@@ -6330,7 +8837,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -6477,7 +8984,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -6624,7 +9131,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -6771,7 +9278,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -6918,7 +9425,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7065,7 +9572,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7212,7 +9719,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7359,7 +9866,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7506,7 +10013,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7653,7 +10160,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7800,7 +10307,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -7947,7 +10454,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -8094,7 +10601,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -8241,7 +10748,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -8388,7 +10895,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -8535,7 +11042,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -8682,10 +11189,10 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0xA0000000, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, +- 0x03E, 0x00001910, ++ 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, +@@ -8707,10 +11214,10 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002C010, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000008, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, +@@ -8731,9 +11238,156 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, + 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000010, +- 0x03E, 0x00001910, ++ 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, +@@ -8757,7 +11411,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, +- 0x03E, 0x00001910, ++ 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, +@@ -8781,7 +11435,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, +- 0x03E, 0x00001910, ++ 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, +@@ -8805,7 +11459,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, +- 0x03E, 0x00001910, ++ 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, +@@ -8829,216 +11483,2478 @@ static const u32 rtw8822c_rf_a[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0xB0000000, 0x00000000, +- 0x0FE, 0x00000000, +- 0x01B, 0x00003A40, +- 0x061, 0x0000D233, +- 0x062, 0x0004D232, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, +- 0xA0000000, 0x00000000, +- 0x063, 0x00000C02, +- 0xB0000000, 0x00000000, +- 0x0EF, 0x00000200, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0xA0000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x0FE, 0x00000000, ++ 0x01B, 0x00003A40, ++ 0x061, 0x0000D233, ++ 0x062, 0x0004D232, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0xA0000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000200, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, + 0x030, 0x00002239, + 0x030, 0x00003239, + 0x030, 0x00004239, +@@ -9063,827 +13979,2362 @@ static const u32 rtw8822c_rf_a[] = { + 0x030, 0x00017239, + 0x030, 0x00018209, + 0x030, 0x00019239, ++ 0xA0000000, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000080, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0xA0000000, 0x00000000, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000040, ++ 0x030, 0x00000770, ++ 0x030, 0x00001770, ++ 0x030, 0x00002440, ++ 0x030, 0x00003440, ++ 0x030, 0x00004330, ++ 0x030, 0x00005330, ++ 0x030, 0x00008770, ++ 0x030, 0x0000A440, ++ 0x030, 0x0000C330, ++ 0x0EF, 0x00000000, ++ 0x0EE, 0x00010000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0xA0000000, 0x00000000, +- 0x030, 0x00000233, +- 0x030, 0x00001233, +- 0x030, 0x00002233, +- 0x030, 0x00003233, +- 0x030, 0x00004203, +- 0x030, 0x00005233, +- 0x030, 0x00006233, +- 0x030, 0x00007233, +- 0x030, 0x00008203, +- 0x030, 0x00009233, +- 0x030, 0x0000A233, +- 0x030, 0x0000B233, +- 0x030, 0x0000C233, +- 0x030, 0x0000D233, +- 0x030, 0x0000E203, +- 0x030, 0x0000F233, +- 0x030, 0x00010233, +- 0x030, 0x00011233, +- 0x030, 0x00012203, +- 0x030, 0x00013233, +- 0x030, 0x00014233, +- 0x030, 0x00015233, +- 0x030, 0x00016203, +- 0x030, 0x00017233, +- 0x030, 0x00018203, +- 0x030, 0x00019233, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EF, 0x00000080, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000281, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000284, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000285, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000286, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000287, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000077, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000281, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000284, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000285, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000286, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000287, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000077, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0xA0000000, 0x00000000, +- 0x030, 0x00000232, +- 0x030, 0x00001232, +- 0x030, 0x00002232, +- 0x030, 0x00003232, +- 0x030, 0x00004232, +- 0x030, 0x00005232, +- 0x030, 0x00006232, +- 0x030, 0x00007232, +- 0x030, 0x00008232, +- 0x030, 0x00009232, +- 0x030, 0x0000A232, +- 0x030, 0x0000B232, +- 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EF, 0x00000040, +- 0x030, 0x00000770, +- 0x030, 0x00001770, +- 0x030, 0x00002440, +- 0x030, 0x00003440, +- 0x030, 0x00004330, +- 0x030, 0x00005330, +- 0x030, 0x00008770, +- 0x030, 0x0000A440, +- 0x030, 0x0000C330, +- 0x0EF, 0x00000000, +- 0x0EE, 0x00010000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, + 0xA0000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0xB0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, + 0x03F, 0x0000006A, +- 0x033, 0x00000201, ++ 0x033, 0x00000301, + 0x03F, 0x0000006D, +- 0x033, 0x00000202, ++ 0x033, 0x00000302, + 0x03F, 0x0000046A, +- 0x033, 0x00000203, ++ 0x033, 0x00000303, + 0x03F, 0x0000086A, +- 0x033, 0x00000204, ++ 0x033, 0x00000304, + 0x03F, 0x00000C89, +- 0x033, 0x00000205, ++ 0x033, 0x00000305, + 0x03F, 0x00000CE8, +- 0x033, 0x00000206, ++ 0x033, 0x00000306, + 0x03F, 0x00000CEB, +- 0x033, 0x00000207, ++ 0x033, 0x00000307, + 0x03F, 0x00000CEE, +- 0x033, 0x00000208, ++ 0x033, 0x00000308, + 0x03F, 0x00000CF1, +- 0x033, 0x00000209, ++ 0x033, 0x00000309, + 0x03F, 0x00000CF4, +- 0x033, 0x0000020A, ++ 0x033, 0x0000030A, + 0x03F, 0x00000CF7, +- 0xB0000000, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000280, ++ 0x0EE, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, + 0x03F, 0x00000005, +- 0x033, 0x00000281, ++ 0x033, 0x00000301, + 0x03F, 0x00000008, +- 0x033, 0x00000282, ++ 0x033, 0x00000302, + 0x03F, 0x0000000B, +- 0x033, 0x00000283, ++ 0x033, 0x00000303, + 0x03F, 0x0000000E, +- 0x033, 0x00000284, ++ 0x033, 0x00000304, + 0x03F, 0x0000002B, +- 0x033, 0x00000285, ++ 0x033, 0x00000305, + 0x03F, 0x0000002E, +- 0x033, 0x00000286, +- 0x03F, 0x0000006B, +- 0x033, 0x00000287, +- 0x03F, 0x0000006E, +- 0x033, 0x00000288, +- 0x03F, 0x00000071, +- 0x033, 0x00000289, +- 0x03F, 0x00000074, +- 0x033, 0x0000028A, +- 0x03F, 0x00000077, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000031, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000034, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000053, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000056, ++ 0x033, 0x0000030A, ++ 0x03F, 0x000000D1, ++ 0x0EE, 0x00000000, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000280, +- 0x03F, 0x00000005, +- 0x033, 0x00000281, +- 0x03F, 0x00000008, +- 0x033, 0x00000282, +- 0x03F, 0x0000000B, +- 0x033, 0x00000283, +- 0x03F, 0x0000000E, +- 0x033, 0x00000284, +- 0x03F, 0x0000002B, +- 0x033, 0x00000285, +- 0x03F, 0x0000002E, +- 0x033, 0x00000286, +- 0x03F, 0x0000006B, +- 0x033, 0x00000287, +- 0x03F, 0x0000006E, +- 0x033, 0x00000288, +- 0x03F, 0x00000071, +- 0x033, 0x00000289, +- 0x03F, 0x00000074, +- 0x033, 0x0000028A, +- 0x03F, 0x00000077, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000280, +- 0x03F, 0x00000005, +- 0x033, 0x00000281, +- 0x03F, 0x00000008, +- 0x033, 0x00000282, +- 0x03F, 0x0000000B, +- 0x033, 0x00000283, +- 0x03F, 0x0000000E, +- 0x033, 0x00000284, +- 0x03F, 0x0000002B, +- 0x033, 0x00000285, +- 0x03F, 0x0000002E, +- 0x033, 0x00000286, +- 0x03F, 0x0000006B, +- 0x033, 0x00000287, +- 0x03F, 0x0000006E, +- 0x033, 0x00000288, +- 0x03F, 0x00000071, +- 0x033, 0x00000289, +- 0x03F, 0x00000074, +- 0x033, 0x0000028A, +- 0x03F, 0x00000077, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000280, ++ 0x033, 0x00000300, + 0x03F, 0x00000005, +- 0x033, 0x00000281, ++ 0x033, 0x00000301, + 0x03F, 0x00000008, +- 0x033, 0x00000282, ++ 0x033, 0x00000302, + 0x03F, 0x0000000B, +- 0x033, 0x00000283, ++ 0x033, 0x00000303, + 0x03F, 0x0000000E, +- 0x033, 0x00000284, ++ 0x033, 0x00000304, + 0x03F, 0x0000002B, +- 0x033, 0x00000285, ++ 0x033, 0x00000305, + 0x03F, 0x0000002E, +- 0x033, 0x00000286, +- 0x03F, 0x0000006B, +- 0x033, 0x00000287, +- 0x03F, 0x0000006E, +- 0x033, 0x00000288, +- 0x03F, 0x00000071, +- 0x033, 0x00000289, +- 0x03F, 0x00000074, +- 0x033, 0x0000028A, +- 0x03F, 0x00000077, +- 0xA0000000, 0x00000000, +- 0x033, 0x00000280, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000031, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000034, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000053, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000056, ++ 0x033, 0x0000030A, ++ 0x03F, 0x000000D1, ++ 0x0EE, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, + 0x03F, 0x0000006A, +- 0x033, 0x00000281, ++ 0x033, 0x00000301, + 0x03F, 0x0000006D, +- 0x033, 0x00000282, ++ 0x033, 0x00000302, + 0x03F, 0x0000046A, +- 0x033, 0x00000283, ++ 0x033, 0x00000303, + 0x03F, 0x0000086A, +- 0x033, 0x00000284, ++ 0x033, 0x00000304, + 0x03F, 0x00000C89, +- 0x033, 0x00000285, ++ 0x033, 0x00000305, + 0x03F, 0x00000CE8, +- 0x033, 0x00000286, ++ 0x033, 0x00000306, + 0x03F, 0x00000CEB, +- 0x033, 0x00000287, ++ 0x033, 0x00000307, + 0x03F, 0x00000CEE, +- 0x033, 0x00000288, ++ 0x033, 0x00000308, + 0x03F, 0x00000CF1, +- 0x033, 0x00000289, ++ 0x033, 0x00000309, + 0x03F, 0x00000CF4, +- 0x033, 0x0000028A, ++ 0x033, 0x0000030A, + 0x03F, 0x00000CF7, +- 0xB0000000, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -9907,7 +16358,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -9931,7 +16382,151 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -9955,7 +16550,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -10005,7 +16600,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x0EE, 0x00000000, + 0xB0000000, 0x00000000, + 0x051, 0x0003C800, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000942CA, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000942CA, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, +@@ -10023,6 +16622,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x052, 0x000902CA, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10037,10 +16638,28 @@ static const u32 rtw8822c_rf_a[] = { + 0x052, 0x000902CA, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0xA0000000, 0x00000000, + 0x052, 0x000942CA, + 0xB0000000, 0x00000000, +@@ -10050,7 +16669,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x0EF, 0x00000020, + 0x033, 0x00000000, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10068,6 +16691,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10082,16 +16707,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000001, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10109,6 +16756,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10123,16 +16772,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10141,39 +16812,63 @@ static const u32 rtw8822c_rf_a[] = { + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00030246, ++ 0x03F, 0x0003D646, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10191,6 +16886,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10205,16 +16902,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000004, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10232,6 +16951,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10246,16 +16967,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000005, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10273,6 +17016,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10287,16 +17032,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10314,6 +17081,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10328,16 +17097,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000007, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10355,6 +17146,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10369,16 +17162,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000008, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10396,6 +17211,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10410,16 +17227,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000009, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10437,6 +17276,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10451,16 +17292,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000A, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10478,6 +17341,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10492,16 +17357,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000B, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10519,6 +17406,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10533,16 +17422,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000C, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10560,6 +17471,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10574,16 +17487,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000D, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10601,6 +17536,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10615,16 +17552,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00028246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00028246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00028246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, +@@ -10642,6 +17601,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10656,16 +17617,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00030246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000F, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10683,6 +17666,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10697,16 +17682,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000010, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10724,6 +17731,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10738,16 +17747,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000011, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10765,6 +17796,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10779,16 +17812,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000012, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10806,6 +17861,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10820,16 +17877,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10847,6 +17926,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10861,16 +17942,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000014, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10888,6 +17991,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10902,16 +18007,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000015, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10929,6 +18056,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10943,16 +18072,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000016, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -10970,6 +18121,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -10984,16 +18137,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000017, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11011,6 +18186,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11025,16 +18202,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000018, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11052,6 +18251,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11066,16 +18267,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000019, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11093,6 +18316,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11107,16 +18332,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001A, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11134,6 +18381,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11148,16 +18397,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001B, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11175,6 +18446,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11189,16 +18462,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001C, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11216,6 +18511,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11230,16 +18527,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001D, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11257,6 +18576,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11271,16 +18592,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00031E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001E, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11298,6 +18641,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11312,16 +18657,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11339,6 +18706,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11353,16 +18722,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000020, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11371,39 +18762,63 @@ static const u32 rtw8822c_rf_a[] = { + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000021, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11421,6 +18836,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11435,16 +18852,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000022, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11462,6 +18901,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11476,16 +18917,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11494,39 +18957,63 @@ static const u32 rtw8822c_rf_a[] = { + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000024, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11544,6 +19031,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11558,16 +19047,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000025, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11585,6 +19096,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11599,16 +19112,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000026, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11617,39 +19152,63 @@ static const u32 rtw8822c_rf_a[] = { + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000027, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11667,6 +19226,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11681,16 +19242,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000028, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11708,6 +19291,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -11722,16 +19307,38 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00025E46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00025E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00025E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000029, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11740,39 +19347,63 @@ static const u32 rtw8822c_rf_a[] = { + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00031E46, ++ 0x03F, 0x0003D646, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0003D646, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000002A, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, +@@ -11790,122 +19421,418 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00021E46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00021E46, ++ 0xA0000000, 0x00000000, ++ 0x03F, 0x00002A46, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EE, 0x00010000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x000008C8, ++ 0x033, 0x00000064, ++ 0x03F, 0x000008CB, ++ 0x033, 0x00000065, ++ 0x03F, 0x000008CE, ++ 0x033, 0x00000066, ++ 0x03F, 0x000008D1, ++ 0x033, 0x00000067, ++ 0x03F, 0x000008D4, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DD1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00021E46, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00002A46, +- 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EE, 0x00010000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -11913,22 +19840,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -11936,22 +19863,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -11959,22 +19886,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -11982,22 +19909,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12005,22 +19932,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12028,22 +19955,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12051,22 +19978,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12074,22 +20001,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12097,22 +20024,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12120,22 +20047,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12143,22 +20070,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12166,22 +20093,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12189,22 +20116,22 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -12212,21 +20139,21 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x000008C8, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x000008CB, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x000008CE, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x000008D1, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x000008D4, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000DD1, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, ++ 0x03F, 0x00000DD7, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000487, +@@ -12251,7 +20178,53 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, +@@ -12458,6 +20431,29 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, +@@ -12504,7 +20500,214 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12527,7 +20730,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12550,7 +20753,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12573,7 +20776,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12596,7 +20799,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12619,7 +20822,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12642,7 +20845,7 @@ static const u32 rtw8822c_rf_a[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, + 0x033, 0x00000021, +@@ -12698,7 +20901,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B0, 0x0001F0FC, + 0x0B1, 0x0007DBE4, + 0x0B2, 0x00022400, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C760, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C760, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, +@@ -12716,6 +20923,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -12730,31 +20939,93 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xB0000000, 0x00000000, + 0x0B4, 0x00099D40, + 0x0B5, 0x0004103F, +- 0x83000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0B6, 0x000387F8, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000387F8, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000387F8, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000187F8, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000387F8, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B6, 0x000387F8, + 0xA0000000, 0x00000000, + 0x0B6, 0x000187F8, + 0xB0000000, 0x00000000, +@@ -12769,7 +21040,11 @@ static const u32 rtw8822c_rf_a[] = { + 0x0CA, 0x00080001, + 0x0FE, 0x00000000, + 0x0B0, 0x0001F0F8, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C700, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C700, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, +@@ -12787,6 +21062,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -12801,10 +21078,28 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C700, + 0xB0000000, 0x00000000, +@@ -12812,7 +21107,11 @@ static const u32 rtw8822c_rf_a[] = { + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C760, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x0007C760, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, +@@ -12830,6 +21129,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -12844,10 +21145,28 @@ static const u32 rtw8822c_rf_a[] = { + 0x0B3, 0x000FC760, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0B3, 0x000FC760, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xB0000000, 0x00000000, +@@ -12871,7 +21190,19 @@ static const u32 rtw8822c_rf_a[] = { + 0x033, 0x00000001, + 0x03F, 0x0000000F, + 0x0ED, 0x00000000, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000500, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, +@@ -12881,6 +21212,8 @@ static const u32 rtw8822c_rf_a[] = { + 0x0DD, 0x00000540, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -12895,10 +21228,28 @@ static const u32 rtw8822c_rf_a[] = { + 0x0DD, 0x00000540, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0DD, 0x00000540, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0DD, 0x00000540, + 0xA0000000, 0x00000000, + 0x0DD, 0x00000500, + 0xB0000000, 0x00000000, +@@ -13008,7 +21359,19 @@ static const u32 rtw8822c_rf_b[] = { + 0x093, 0x0008483F, + 0x0EF, 0x00080000, + 0x033, 0x00000001, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00091230, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, +@@ -13018,6 +21381,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0009123E, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -13032,16 +21397,38 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0009123E, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0009123E, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0009123E, + 0xA0000000, 0x00000000, + 0x03F, 0x00091230, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0DE, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, +@@ -13059,6 +21446,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x08E, 0x000A5540, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -13073,10 +21462,28 @@ static const u32 rtw8822c_rf_b[] = { + 0x08E, 0x000A5540, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x08E, 0x000A5540, + 0xA0000000, 0x00000000, + 0x08E, 0x000A5540, + 0xB0000000, 0x00000000, +@@ -13084,7 +21491,25 @@ static const u32 rtw8822c_rf_b[] = { + 0x081, 0x0002FC01, + 0x081, 0x0003FC01, + 0x085, 0x0006A06C, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000003F, ++ 0x0EE, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000003F, ++ 0x0EE, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, +@@ -13130,133 +21555,691 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000002A, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000002A, ++ 0x0EE, 0x00000000, ++ 0xA0000000, 0x00000000, ++ 0x0EE, 0x00000010, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000001, ++ 0x03F, 0x0000003F, ++ 0x033, 0x00000002, ++ 0x03F, 0x0000003F, ++ 0x0EE, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000001, +- 0x03F, 0x0000002A, +- 0x033, 0x00000002, +- 0x03F, 0x0000002A, +- 0x0EE, 0x00000000, +- 0xA0000000, 0x00000000, +- 0x0EE, 0x00000010, +- 0x033, 0x00000001, +- 0x03F, 0x0000003F, +- 0x033, 0x00000001, +- 0x03F, 0x0000003F, +- 0x033, 0x00000002, +- 0x03F, 0x0000003F, +- 0x0EE, 0x00000000, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13282,7 +22265,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13308,7 +22291,85 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13334,7 +22395,33 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00010000, ++ 0x033, 0x0000000F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000000E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000000D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000000C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000000B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000000A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000009, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000008, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000007, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000006, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000005, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000004, ++ 0x03F, 0x00000040, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13345,11 +22432,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, +@@ -13360,7 +22447,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13386,7 +22473,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13412,7 +22499,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13438,7 +22525,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, +@@ -13464,18 +22551,18 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0xA0000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000000E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000000D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000000C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000000B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, +@@ -13490,270 +22577,560 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000003, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000280, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000280, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000280, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000016, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000015, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000001E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000001D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000001C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000001B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000001A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000019, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000018, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, ++ 0x033, 0x0000001F, + 0x03F, 0x000773C0, +- 0x033, 0x0000000E, ++ 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000000D, ++ 0x033, 0x0000001D, + 0x03F, 0x000773E8, +- 0x033, 0x0000000C, ++ 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000000B, ++ 0x033, 0x0000001B, + 0x03F, 0x00000287, +- 0x033, 0x0000000A, ++ 0x033, 0x0000001A, + 0x03F, 0x000002A8, +- 0x033, 0x00000009, ++ 0x033, 0x00000019, + 0x03F, 0x00000207, +- 0x033, 0x00000008, +- 0x03F, 0x000FF280, +- 0x033, 0x00000007, +- 0x03F, 0x00000200, +- 0x033, 0x00000006, +- 0x03F, 0x000001C0, +- 0x033, 0x00000005, +- 0x03F, 0x00000180, +- 0x033, 0x00000004, +- 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, +- 0x0EF, 0x00010000, +- 0x033, 0x0000000F, +- 0x03F, 0x000773E8, +- 0x033, 0x0000000E, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000000D, +- 0x03F, 0x00000380, +- 0x033, 0x0000000C, +- 0x03F, 0x000FF380, +- 0x033, 0x0000000B, +- 0x03F, 0x00000300, +- 0x033, 0x0000000A, +- 0x03F, 0x000002A8, +- 0x033, 0x00000009, +- 0x03F, 0x00000280, +- 0x033, 0x00000008, ++ 0x033, 0x00000018, + 0x03F, 0x000FF280, +- 0x033, 0x00000007, ++ 0x033, 0x00000017, + 0x03F, 0x00000200, +- 0x033, 0x00000006, ++ 0x033, 0x00000016, + 0x03F, 0x000001C0, +- 0x033, 0x00000005, ++ 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000004, ++ 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000003, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13778,7 +23155,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13803,7 +23180,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13813,11 +23190,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, +@@ -13828,7 +23205,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13838,11 +23215,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, +@@ -13853,7 +23230,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13878,7 +23255,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13903,7 +23280,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13928,7 +23305,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, +@@ -13953,17 +23330,17 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0xA0000000, 0x00000000, + 0x033, 0x0000001F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000001E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000001D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000001C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000001B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, +@@ -13976,262 +23353,662 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000014, ++ 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000013, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000040, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000026, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000280, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000280, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000280, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, +- 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, +- 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, + 0x03F, 0x000773C0, +- 0x033, 0x0000001E, ++ 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000001D, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001C, ++ 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000001B, ++ 0x033, 0x0000002B, + 0x03F, 0x00000287, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, ++ 0x033, 0x00000029, + 0x03F, 0x00000207, +- 0x033, 0x00000018, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, +- 0x033, 0x0000001F, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000002F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000002E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000002D, + 0x03F, 0x000773E8, +- 0x033, 0x0000001E, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000001D, +- 0x03F, 0x00000380, +- 0x033, 0x0000001C, +- 0x03F, 0x000FF380, +- 0x033, 0x0000001B, +- 0x03F, 0x00000300, +- 0x033, 0x0000001A, ++ 0x033, 0x0000002C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000002B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000002A, + 0x03F, 0x000002A8, +- 0x033, 0x00000019, +- 0x03F, 0x00000280, +- 0x033, 0x00000018, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000028, + 0x03F, 0x000FF280, +- 0x033, 0x00000017, ++ 0x033, 0x00000027, + 0x03F, 0x00000200, +- 0x033, 0x00000016, ++ 0x033, 0x00000026, + 0x03F, 0x000001C0, +- 0x033, 0x00000015, ++ 0x033, 0x00000025, + 0x03F, 0x00000180, +- 0x033, 0x00000014, ++ 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000013, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -14256,7 +24033,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -14281,7 +24058,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -14291,11 +24068,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, +@@ -14306,7 +24083,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, +@@ -14316,11 +24093,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, +@@ -14331,17 +24108,17 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0xA0000000, 0x00000000, + 0x033, 0x0000002F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000002E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000002D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000002C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000002B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, +@@ -14356,360 +24133,560 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000037, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000036, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000035, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000034, ++ 0x03F, 0x00000040, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, +- 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, +- 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, +- 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, +- 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, + 0x03F, 0x000773C0, +- 0x033, 0x0000002E, ++ 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000002D, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002C, ++ 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000002B, ++ 0x033, 0x0000003B, + 0x03F, 0x00000287, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, ++ 0x033, 0x00000039, + 0x03F, 0x00000207, +- 0x033, 0x00000028, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, +- 0x033, 0x0000002F, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000003F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000003E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000003D, + 0x03F, 0x000773E8, +- 0x033, 0x0000002E, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000002D, +- 0x03F, 0x00000380, +- 0x033, 0x0000002C, +- 0x03F, 0x000FF380, +- 0x033, 0x0000002B, +- 0x03F, 0x00000300, +- 0x033, 0x0000002A, ++ 0x033, 0x0000003C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000003B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000003A, + 0x03F, 0x000002A8, +- 0x033, 0x00000029, +- 0x03F, 0x00000280, +- 0x033, 0x00000028, ++ 0x033, 0x00000039, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000038, + 0x03F, 0x000FF280, +- 0x033, 0x00000027, ++ 0x033, 0x00000037, + 0x03F, 0x00000200, +- 0x033, 0x00000026, ++ 0x033, 0x00000036, + 0x03F, 0x000001C0, +- 0x033, 0x00000025, ++ 0x033, 0x00000035, + 0x03F, 0x00000180, +- 0x033, 0x00000024, ++ 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000023, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14734,7 +24711,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14759,7 +24736,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14769,11 +24746,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -14784,7 +24761,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14794,11 +24771,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, +@@ -14809,7 +24786,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14834,7 +24811,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14859,7 +24836,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14884,7 +24861,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, +@@ -14909,17 +24886,17 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0xA0000000, 0x00000000, + 0x033, 0x0000003F, +- 0x03F, 0x000773C0, ++ 0x03F, 0x000773E8, + 0x033, 0x0000003E, +- 0x03F, 0x000FF3C0, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000003D, +- 0x03F, 0x000773E8, ++ 0x03F, 0x00000380, + 0x033, 0x0000003C, +- 0x03F, 0x000FF3E8, ++ 0x03F, 0x000FF380, + 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000300, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, +@@ -14934,260 +24911,385 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000033, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, +- 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, +- 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, +- 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, +- 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, +- 0x03F, 0x000FF3A0, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, +- 0x03F, 0x00000280, +- 0x033, 0x00000038, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, ++ 0x033, 0x0000004B, + 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, +- 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, +- 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, ++ 0x033, 0x0000004B, + 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, + 0x03F, 0x000773C0, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000003D, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003C, ++ 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000003B, ++ 0x033, 0x0000004B, + 0x03F, 0x00000287, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000207, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, +- 0x033, 0x0000003F, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000004D, + 0x03F, 0x000773E8, +- 0x033, 0x0000003E, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000003D, +- 0x03F, 0x00000380, +- 0x033, 0x0000003C, +- 0x03F, 0x000FF380, +- 0x033, 0x0000003B, +- 0x03F, 0x00000300, +- 0x033, 0x0000003A, ++ 0x033, 0x0000004A, + 0x03F, 0x000002A8, +- 0x033, 0x00000039, ++ 0x033, 0x00000049, + 0x03F, 0x00000280, +- 0x033, 0x00000038, ++ 0x033, 0x00000048, + 0x03F, 0x000FF280, +- 0x033, 0x00000037, ++ 0x033, 0x00000047, + 0x03F, 0x00000200, +- 0x033, 0x00000036, ++ 0x033, 0x00000046, + 0x03F, 0x000001C0, +- 0x033, 0x00000035, ++ 0x033, 0x00000045, + 0x03F, 0x00000180, +- 0x033, 0x00000034, ++ 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000033, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15212,7 +25314,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15222,11 +25324,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -15237,7 +25339,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15247,11 +25349,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -15262,7 +25364,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15287,7 +25389,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15312,7 +25414,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15322,11 +25424,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -15337,7 +25439,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15362,7 +25464,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15372,11 +25474,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, +@@ -15387,7 +25489,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15412,7 +25514,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15437,7 +25539,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15462,7 +25564,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15487,7 +25589,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15512,7 +25614,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15537,7 +25639,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, +@@ -15546,126 +25648,326 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000004B, +- 0x03F, 0x00000287, +- 0x033, 0x0000004A, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000287, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000207, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0xA0000000, 0x00000000, ++ 0x033, 0x0000004F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000004E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000004D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000004C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000004B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000004A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000049, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000048, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000047, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000046, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000045, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000044, ++ 0x03F, 0x00000040, ++ 0xB0000000, 0x00000000, ++ 0x033, 0x00000043, ++ 0x03F, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x00000380, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF380, ++ 0x033, 0x0000005B, ++ 0x03F, 0x00000300, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, + 0x03F, 0x000002A8, +- 0x033, 0x00000049, +- 0x03F, 0x00000207, +- 0x033, 0x00000048, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, + 0x03F, 0x000FF280, +- 0x033, 0x00000047, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, +- 0x033, 0x00000046, ++ 0x033, 0x00000056, + 0x03F, 0x000001C0, +- 0x033, 0x00000045, ++ 0x033, 0x00000055, + 0x03F, 0x00000180, +- 0x033, 0x00000044, ++ 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000004F, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, + 0x03F, 0x000773C0, +- 0x033, 0x0000004E, ++ 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000004D, ++ 0x033, 0x0000005D, + 0x03F, 0x000773E8, +- 0x033, 0x0000004C, ++ 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000004B, ++ 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000004A, ++ 0x033, 0x0000005A, + 0x03F, 0x000002A8, +- 0x033, 0x00000049, ++ 0x033, 0x00000059, + 0x03F, 0x00000280, +- 0x033, 0x00000048, ++ 0x033, 0x00000058, + 0x03F, 0x000FF280, +- 0x033, 0x00000047, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, +- 0x033, 0x00000046, ++ 0x033, 0x00000056, + 0x03F, 0x000001C0, +- 0x033, 0x00000045, ++ 0x033, 0x00000055, + 0x03F, 0x00000180, +- 0x033, 0x00000044, ++ 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000004F, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, + 0x03F, 0x000773C0, +- 0x033, 0x0000004E, ++ 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000004D, ++ 0x033, 0x0000005D, + 0x03F, 0x000773E8, +- 0x033, 0x0000004C, ++ 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000004B, ++ 0x033, 0x0000005B, + 0x03F, 0x00000287, +- 0x033, 0x0000004A, ++ 0x033, 0x0000005A, + 0x03F, 0x000002A8, +- 0x033, 0x00000049, ++ 0x033, 0x00000059, + 0x03F, 0x00000207, +- 0x033, 0x00000048, ++ 0x033, 0x00000058, + 0x03F, 0x000FF280, +- 0x033, 0x00000047, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, +- 0x033, 0x00000046, ++ 0x033, 0x00000056, + 0x03F, 0x000001C0, +- 0x033, 0x00000045, ++ 0x033, 0x00000055, + 0x03F, 0x00000180, +- 0x033, 0x00000044, ++ 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x0000004F, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, + 0x03F, 0x000773C0, +- 0x033, 0x0000004E, ++ 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, +- 0x033, 0x0000004D, ++ 0x033, 0x0000005D, + 0x03F, 0x000773E8, +- 0x033, 0x0000004C, ++ 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, +- 0x033, 0x0000004B, ++ 0x033, 0x0000005B, + 0x03F, 0x00000287, +- 0x033, 0x0000004A, ++ 0x033, 0x0000005A, + 0x03F, 0x000002A8, +- 0x033, 0x00000049, ++ 0x033, 0x00000059, + 0x03F, 0x00000207, +- 0x033, 0x00000048, ++ 0x033, 0x00000058, + 0x03F, 0x000FF280, +- 0x033, 0x00000047, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, +- 0x033, 0x00000046, ++ 0x033, 0x00000056, + 0x03F, 0x000001C0, +- 0x033, 0x00000045, ++ 0x033, 0x00000055, + 0x03F, 0x00000180, +- 0x033, 0x00000044, ++ 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0xA0000000, 0x00000000, +- 0x033, 0x0000004F, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, + 0x03F, 0x000773E8, +- 0x033, 0x0000004E, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, +- 0x033, 0x0000004D, +- 0x03F, 0x00000380, +- 0x033, 0x0000004C, +- 0x03F, 0x000FF380, +- 0x033, 0x0000004B, +- 0x03F, 0x00000300, +- 0x033, 0x0000004A, ++ 0x033, 0x0000005A, + 0x03F, 0x000002A8, +- 0x033, 0x00000049, ++ 0x033, 0x00000059, + 0x03F, 0x00000280, +- 0x033, 0x00000048, ++ 0x033, 0x00000058, + 0x03F, 0x000FF280, +- 0x033, 0x00000047, ++ 0x033, 0x00000057, + 0x03F, 0x00000200, +- 0x033, 0x00000046, ++ 0x033, 0x00000056, + 0x03F, 0x000001C0, +- 0x033, 0x00000045, ++ 0x033, 0x00000055, + 0x03F, 0x00000180, +- 0x033, 0x00000044, ++ 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000043, +- 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15690,7 +25992,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15700,11 +26002,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, +@@ -15715,7 +26017,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15725,11 +26027,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, +@@ -15740,7 +26042,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15765,7 +26067,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15790,7 +26092,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15800,11 +26102,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, +- 0x03F, 0x000FF3A0, ++ 0x03F, 0x00000287, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, +- 0x03F, 0x00000280, ++ 0x03F, 0x00000207, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, +@@ -15815,7 +26117,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15840,7 +26142,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15850,11 +26152,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, +- 0x03F, 0x00000287, ++ 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, +- 0x03F, 0x00000207, ++ 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, +@@ -15865,7 +26167,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15890,7 +26192,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15915,7 +26217,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15940,7 +26242,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15965,7 +26267,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -15990,7 +26292,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -16015,7 +26317,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -16040,7 +26342,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -16065,7 +26367,32 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000005F, ++ 0x03F, 0x000773C0, ++ 0x033, 0x0000005E, ++ 0x03F, 0x000FF3C0, ++ 0x033, 0x0000005D, ++ 0x03F, 0x000773E8, ++ 0x033, 0x0000005C, ++ 0x03F, 0x000FF3E8, ++ 0x033, 0x0000005B, ++ 0x03F, 0x000FF3A0, ++ 0x033, 0x0000005A, ++ 0x03F, 0x000002A8, ++ 0x033, 0x00000059, ++ 0x03F, 0x00000280, ++ 0x033, 0x00000058, ++ 0x03F, 0x000FF280, ++ 0x033, 0x00000057, ++ 0x03F, 0x00000200, ++ 0x033, 0x00000056, ++ 0x03F, 0x000001C0, ++ 0x033, 0x00000055, ++ 0x03F, 0x00000180, ++ 0x033, 0x00000054, ++ 0x03F, 0x00000040, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -16090,7 +26417,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, +@@ -16143,60 +26470,1701 @@ static const u32 rtw8822c_rf_b[] = { + 0xB0000000, 0x00000000, + 0x033, 0x00000053, + 0x03F, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0xA0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x08A, 0x000E7DE3, ++ 0x08B, 0x0008FE00, ++ 0x0EE, 0x00000008, ++ 0x033, 0x00000000, ++ 0x03F, 0x00000023, ++ 0x033, 0x00000001, ++ 0x03F, 0x00000023, ++ 0x0EE, 0x00000000, ++ 0x0EF, 0x00004000, ++ 0x033, 0x00000000, ++ 0x03F, 0x0000000F, ++ 0x033, 0x00000002, ++ 0x03F, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0xA0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0xB0000000, 0x00000000, +- 0x08A, 0x000E7DE3, +- 0x08B, 0x0008FE00, +- 0x0EE, 0x00000008, ++ 0x0EF, 0x00020000, + 0x033, 0x00000000, +- 0x03F, 0x00000023, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, + 0x033, 0x00000001, +- 0x03F, 0x00000023, +- 0x0EE, 0x00000000, +- 0x0EF, 0x00004000, +- 0x033, 0x00000000, +- 0x03F, 0x0000000F, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, + 0x033, 0x00000002, +- 0x03F, 0x00000000, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -16343,7 +28311,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -16368,7 +28336,154 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, + 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, +@@ -16490,7 +28605,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -16637,7 +28752,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -16784,7 +28899,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -16931,7 +29046,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17078,7 +29193,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17225,7 +29340,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17372,7 +29487,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17397,7 +29512,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002C010, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, +@@ -17519,7 +29634,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17666,7 +29781,154 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17691,7 +29953,154 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000008, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002F81C, ++ 0x033, 0x00000009, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000000F, ++ 0x03E, 0x00000000, + 0x03F, 0x0002F81C, ++ 0x033, 0x00000010, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000011, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000012, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000013, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000014, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000015, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000016, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000017, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000018, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000019, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000001F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000020, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000021, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000022, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000023, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000024, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000025, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000026, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000027, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x033, 0x00000028, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000029, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002A, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002B, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002C, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002D, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002E, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x0000002F, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, ++ 0x0EF, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EF, 0x00020000, ++ 0x033, 0x00000000, ++ 0x03E, 0x00001C86, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000001, ++ 0x03E, 0x00001C02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000002, ++ 0x03E, 0x00000F02, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000003, ++ 0x03E, 0x00000F00, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000004, ++ 0x03E, 0x00000086, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000005, ++ 0x03E, 0x00000002, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000006, ++ 0x03E, 0x00000000, ++ 0x03F, 0x00020000, ++ 0x033, 0x00000007, ++ 0x03E, 0x00000000, ++ 0x03F, 0x0002C010, + 0x033, 0x00000008, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, +@@ -17813,7 +30222,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -17960,7 +30369,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -18107,7 +30516,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -18254,7 +30663,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -18279,7 +30688,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002C010, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, +@@ -18401,7 +30810,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, +@@ -18426,7 +30835,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002C010, ++ 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, +@@ -18548,10 +30957,10 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0xA0000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, +@@ -18573,10 +30982,10 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03F, 0x0002C010, + 0x033, 0x00000008, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03E, 0x00001910, ++ 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, +@@ -18597,9 +31006,9 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, ++ 0x03F, 0x0002C010, + 0x033, 0x00000010, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, +@@ -18623,7 +31032,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, +@@ -18647,7 +31056,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, +@@ -18671,7 +31080,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, +- 0x03E, 0x00001C86, ++ 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, +@@ -18695,1285 +31104,2691 @@ static const u32 rtw8822c_rf_b[] = { + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, ++ 0xB0000000, 0x00000000, ++ 0x0FE, 0x00000000, ++ 0x01B, 0x00003A40, ++ 0x061, 0x0000D233, ++ 0x062, 0x0004D232, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x063, 0x00000002, ++ 0xA0000000, 0x00000000, ++ 0x063, 0x00000C02, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000200, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000237, ++ 0x030, 0x00001237, ++ 0x030, 0x00002237, ++ 0x030, 0x00003237, ++ 0x030, 0x00004207, ++ 0x030, 0x00005237, ++ 0x030, 0x00006237, ++ 0x030, 0x00007237, ++ 0x030, 0x00008207, ++ 0x030, 0x00009237, ++ 0x030, 0x0000A237, ++ 0x030, 0x0000B237, ++ 0x030, 0x0000C237, ++ 0x030, 0x0000D237, ++ 0x030, 0x0000E207, ++ 0x030, 0x0000F237, ++ 0x030, 0x00010237, ++ 0x030, 0x00011237, ++ 0x030, 0x00012207, ++ 0x030, 0x00013237, ++ 0x030, 0x00014237, ++ 0x030, 0x00015237, ++ 0x030, 0x00016207, ++ 0x030, 0x00017237, ++ 0x030, 0x00018207, ++ 0x030, 0x00019237, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x0EF, 0x00020000, +- 0x033, 0x00000000, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000001, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000002, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000003, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000004, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000005, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000006, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000007, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, +- 0x033, 0x00000008, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, +- 0x033, 0x00000009, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000000A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000000B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000000C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000000D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000000E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000000F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002F81C, +- 0x033, 0x00000010, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000011, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000012, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000013, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000014, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000015, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000016, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000017, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000018, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000019, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000001A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000001B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000001C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000001D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000001E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000001F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000020, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000021, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000022, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000023, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000024, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000025, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000026, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000027, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000028, +- 0x03E, 0x00001C86, +- 0x03F, 0x00020000, +- 0x033, 0x00000029, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000002A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000002B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000002C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000002D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000002E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000002F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x0EF, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000238, ++ 0x030, 0x00001238, ++ 0x030, 0x00002238, ++ 0x030, 0x00003238, ++ 0x030, 0x00004228, ++ 0x030, 0x00005238, ++ 0x030, 0x00006238, ++ 0x030, 0x00007238, ++ 0x030, 0x00008228, ++ 0x030, 0x00009238, ++ 0x030, 0x0000A238, ++ 0x030, 0x0000B238, ++ 0x030, 0x0000C238, ++ 0x030, 0x0000D238, ++ 0x030, 0x0000E228, ++ 0x030, 0x0000F238, ++ 0x030, 0x00010238, ++ 0x030, 0x00011238, ++ 0x030, 0x00012228, ++ 0x030, 0x00013238, ++ 0x030, 0x00014238, ++ 0x030, 0x00015238, ++ 0x030, 0x00016228, ++ 0x030, 0x00017238, ++ 0x030, 0x00018228, ++ 0x030, 0x00019238, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000239, ++ 0x030, 0x00001239, ++ 0x030, 0x00002239, ++ 0x030, 0x00003239, ++ 0x030, 0x00004239, ++ 0x030, 0x00005239, ++ 0x030, 0x00006239, ++ 0x030, 0x00007239, ++ 0x030, 0x00008239, ++ 0x030, 0x00009239, ++ 0x030, 0x0000A239, ++ 0x030, 0x0000B239, ++ 0x030, 0x0000C239, ++ 0x030, 0x0000D239, ++ 0x030, 0x0000E209, ++ 0x030, 0x0000F239, ++ 0x030, 0x00010239, ++ 0x030, 0x00011239, ++ 0x030, 0x00012209, ++ 0x030, 0x00013239, ++ 0x030, 0x00014239, ++ 0x030, 0x00015239, ++ 0x030, 0x00016209, ++ 0x030, 0x00017239, ++ 0x030, 0x00018209, ++ 0x030, 0x00019239, + 0xA0000000, 0x00000000, +- 0x0EF, 0x00020000, +- 0x033, 0x00000000, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000001, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000002, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000003, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000004, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000005, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000006, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000007, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000008, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000009, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000000A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000000B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000000C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000000D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000000E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000000F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000010, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000011, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000012, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000013, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000014, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000015, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000016, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000017, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000018, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000019, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000001A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000001B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000001C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000001D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000001E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000001F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000020, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000021, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x00000022, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x00000023, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x00000024, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x00000025, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x00000026, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x00000027, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x033, 0x00000028, +- 0x03E, 0x00001910, +- 0x03F, 0x00020000, +- 0x033, 0x00000029, +- 0x03E, 0x00001C02, +- 0x03F, 0x00020000, +- 0x033, 0x0000002A, +- 0x03E, 0x00000F02, +- 0x03F, 0x00020000, +- 0x033, 0x0000002B, +- 0x03E, 0x00000F00, +- 0x03F, 0x00020000, +- 0x033, 0x0000002C, +- 0x03E, 0x00000086, +- 0x03F, 0x00020000, +- 0x033, 0x0000002D, +- 0x03E, 0x00000002, +- 0x03F, 0x00020000, +- 0x033, 0x0000002E, +- 0x03E, 0x00000000, +- 0x03F, 0x00020000, +- 0x033, 0x0000002F, +- 0x03E, 0x00000000, +- 0x03F, 0x0002C010, +- 0x0EF, 0x00000000, ++ 0x030, 0x00000233, ++ 0x030, 0x00001233, ++ 0x030, 0x00002233, ++ 0x030, 0x00003233, ++ 0x030, 0x00004203, ++ 0x030, 0x00005233, ++ 0x030, 0x00006233, ++ 0x030, 0x00007233, ++ 0x030, 0x00008203, ++ 0x030, 0x00009233, ++ 0x030, 0x0000A233, ++ 0x030, 0x0000B233, ++ 0x030, 0x0000C233, ++ 0x030, 0x0000D233, ++ 0x030, 0x0000E203, ++ 0x030, 0x0000F233, ++ 0x030, 0x00010233, ++ 0x030, 0x00011233, ++ 0x030, 0x00012203, ++ 0x030, 0x00013233, ++ 0x030, 0x00014233, ++ 0x030, 0x00015233, ++ 0x030, 0x00016203, ++ 0x030, 0x00017233, ++ 0x030, 0x00018203, ++ 0x030, 0x00019233, + 0xB0000000, 0x00000000, +- 0x0FE, 0x00000000, +- 0x01B, 0x00003A40, +- 0x061, 0x0000D233, +- 0x062, 0x0004D232, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000080, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x063, 0x00000002, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x030, 0x00000334, ++ 0x030, 0x00001334, ++ 0x030, 0x00002334, ++ 0x030, 0x00003334, ++ 0x030, 0x00004334, ++ 0x030, 0x00005334, ++ 0x030, 0x00006334, ++ 0x030, 0x00007334, ++ 0x030, 0x00008334, ++ 0x030, 0x00009334, ++ 0x030, 0x0000A334, ++ 0x030, 0x0000B334, + 0xA0000000, 0x00000000, +- 0x063, 0x00000C02, ++ 0x030, 0x00000232, ++ 0x030, 0x00001232, ++ 0x030, 0x00002232, ++ 0x030, 0x00003232, ++ 0x030, 0x00004232, ++ 0x030, 0x00005232, ++ 0x030, 0x00006232, ++ 0x030, 0x00007232, ++ 0x030, 0x00008232, ++ 0x030, 0x00009232, ++ 0x030, 0x0000A232, ++ 0x030, 0x0000B232, + 0xB0000000, 0x00000000, +- 0x0EF, 0x00000200, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, ++ 0x0EF, 0x00000000, ++ 0x0EF, 0x00000040, ++ 0x030, 0x00000770, ++ 0x030, 0x00001770, ++ 0x030, 0x00002440, ++ 0x030, 0x00003440, ++ 0x030, 0x00004330, ++ 0x030, 0x00005330, ++ 0x030, 0x00008770, ++ 0x030, 0x0000A440, ++ 0x030, 0x0000C330, ++ 0x0EF, 0x00000000, ++ 0x0EE, 0x00010000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000237, +- 0x030, 0x00001237, +- 0x030, 0x00002237, +- 0x030, 0x00003237, +- 0x030, 0x00004207, +- 0x030, 0x00005237, +- 0x030, 0x00006237, +- 0x030, 0x00007237, +- 0x030, 0x00008207, +- 0x030, 0x00009237, +- 0x030, 0x0000A237, +- 0x030, 0x0000B237, +- 0x030, 0x0000C237, +- 0x030, 0x0000D237, +- 0x030, 0x0000E207, +- 0x030, 0x0000F237, +- 0x030, 0x00010237, +- 0x030, 0x00011237, +- 0x030, 0x00012207, +- 0x030, 0x00013237, +- 0x030, 0x00014237, +- 0x030, 0x00015237, +- 0x030, 0x00016207, +- 0x030, 0x00017237, +- 0x030, 0x00018207, +- 0x030, 0x00019237, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000238, +- 0x030, 0x00001238, +- 0x030, 0x00002238, +- 0x030, 0x00003238, +- 0x030, 0x00004228, +- 0x030, 0x00005238, +- 0x030, 0x00006238, +- 0x030, 0x00007238, +- 0x030, 0x00008228, +- 0x030, 0x00009238, +- 0x030, 0x0000A238, +- 0x030, 0x0000B238, +- 0x030, 0x0000C238, +- 0x030, 0x0000D238, +- 0x030, 0x0000E228, +- 0x030, 0x0000F238, +- 0x030, 0x00010238, +- 0x030, 0x00011238, +- 0x030, 0x00012228, +- 0x030, 0x00013238, +- 0x030, 0x00014238, +- 0x030, 0x00015238, +- 0x030, 0x00016228, +- 0x030, 0x00017238, +- 0x030, 0x00018228, +- 0x030, 0x00019238, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000239, +- 0x030, 0x00001239, +- 0x030, 0x00002239, +- 0x030, 0x00003239, +- 0x030, 0x00004239, +- 0x030, 0x00005239, +- 0x030, 0x00006239, +- 0x030, 0x00007239, +- 0x030, 0x00008239, +- 0x030, 0x00009239, +- 0x030, 0x0000A239, +- 0x030, 0x0000B239, +- 0x030, 0x0000C239, +- 0x030, 0x0000D239, +- 0x030, 0x0000E209, +- 0x030, 0x0000F239, +- 0x030, 0x00010239, +- 0x030, 0x00011239, +- 0x030, 0x00012209, +- 0x030, 0x00013239, +- 0x030, 0x00014239, +- 0x030, 0x00015239, +- 0x030, 0x00016209, +- 0x030, 0x00017239, +- 0x030, 0x00018209, +- 0x030, 0x00019239, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000200, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000201, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000204, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000205, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000206, ++ 0x03F, 0x0000006B, ++ 0x033, 0x00000207, ++ 0x03F, 0x0000006E, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000071, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000074, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000077, + 0xA0000000, 0x00000000, +- 0x030, 0x00000233, +- 0x030, 0x00001233, +- 0x030, 0x00002233, +- 0x030, 0x00003233, +- 0x030, 0x00004203, +- 0x030, 0x00005233, +- 0x030, 0x00006233, +- 0x030, 0x00007233, +- 0x030, 0x00008203, +- 0x030, 0x00009233, +- 0x030, 0x0000A233, +- 0x030, 0x0000B233, +- 0x030, 0x0000C233, +- 0x030, 0x0000D233, +- 0x030, 0x0000E203, +- 0x030, 0x0000F233, +- 0x030, 0x00010233, +- 0x030, 0x00011233, +- 0x030, 0x00012203, +- 0x030, 0x00013233, +- 0x030, 0x00014233, +- 0x030, 0x00015233, +- 0x030, 0x00016203, +- 0x030, 0x00017233, +- 0x030, 0x00018203, +- 0x030, 0x00019233, ++ 0x033, 0x00000200, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000201, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000202, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000203, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000204, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000205, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000206, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000207, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000208, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000209, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000020A, ++ 0x03F, 0x00000CF7, + 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EF, 0x00000080, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x030, 0x00000334, +- 0x030, 0x00001334, +- 0x030, 0x00002334, +- 0x030, 0x00003334, +- 0x030, 0x00004334, +- 0x030, 0x00005334, +- 0x030, 0x00006334, +- 0x030, 0x00007334, +- 0x030, 0x00008334, +- 0x030, 0x00009334, +- 0x030, 0x0000A334, +- 0x030, 0x0000B334, +- 0xA0000000, 0x00000000, +- 0x030, 0x00000232, +- 0x030, 0x00001232, +- 0x030, 0x00002232, +- 0x030, 0x00003232, +- 0x030, 0x00004232, +- 0x030, 0x00005232, +- 0x030, 0x00006232, +- 0x030, 0x00007232, +- 0x030, 0x00008232, +- 0x030, 0x00009232, +- 0x030, 0x0000A232, +- 0x030, 0x0000B232, +- 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EF, 0x00000040, +- 0x030, 0x00000770, +- 0x030, 0x00001770, +- 0x030, 0x00002440, +- 0x030, 0x00003440, +- 0x030, 0x00004330, +- 0x030, 0x00005330, +- 0x030, 0x00008770, +- 0x030, 0x0000A440, +- 0x030, 0x0000C330, +- 0x0EF, 0x00000000, +- 0x0EE, 0x00010000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x033, 0x00000280, + 0x03F, 0x00000005, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x00000008, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000000B, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000000E, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x0000002B, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x0000002E, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x0000006B, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x0000006E, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000071, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000074, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000077, +- 0xA0000000, 0x00000000, +- 0x033, 0x00000200, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, + 0x03F, 0x0000006A, +- 0x033, 0x00000201, ++ 0x033, 0x00000281, + 0x03F, 0x0000006D, +- 0x033, 0x00000202, ++ 0x033, 0x00000282, + 0x03F, 0x0000046A, +- 0x033, 0x00000203, ++ 0x033, 0x00000283, + 0x03F, 0x0000086A, +- 0x033, 0x00000204, ++ 0x033, 0x00000284, + 0x03F, 0x00000C89, +- 0x033, 0x00000205, ++ 0x033, 0x00000285, + 0x03F, 0x00000CE8, +- 0x033, 0x00000206, ++ 0x033, 0x00000286, + 0x03F, 0x00000CEB, +- 0x033, 0x00000207, ++ 0x033, 0x00000287, + 0x03F, 0x00000CEE, +- 0x033, 0x00000208, ++ 0x033, 0x00000288, + 0x03F, 0x00000CF1, +- 0x033, 0x00000209, ++ 0x033, 0x00000289, + 0x03F, 0x00000CF4, +- 0x033, 0x0000020A, ++ 0x033, 0x0000028A, + 0x03F, 0x00000CF7, +- 0xB0000000, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000280, +- 0x03F, 0x00000005, ++ 0x03F, 0x0000006A, + 0x033, 0x00000281, +- 0x03F, 0x00000008, ++ 0x03F, 0x0000006D, + 0x033, 0x00000282, +- 0x03F, 0x0000000B, ++ 0x03F, 0x0000046A, + 0x033, 0x00000283, +- 0x03F, 0x0000000E, ++ 0x03F, 0x0000086A, + 0x033, 0x00000284, +- 0x03F, 0x0000002B, ++ 0x03F, 0x00000C89, + 0x033, 0x00000285, +- 0x03F, 0x0000002E, ++ 0x03F, 0x00000CE8, + 0x033, 0x00000286, +- 0x03F, 0x0000006B, ++ 0x03F, 0x00000CEB, + 0x033, 0x00000287, +- 0x03F, 0x0000006E, ++ 0x03F, 0x00000CEE, + 0x033, 0x00000288, +- 0x03F, 0x00000071, ++ 0x03F, 0x00000CF1, + 0x033, 0x00000289, +- 0x03F, 0x00000074, ++ 0x03F, 0x00000CF4, + 0x033, 0x0000028A, +- 0x03F, 0x00000077, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000CF7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000280, +- 0x03F, 0x00000005, ++ 0x03F, 0x0000006A, + 0x033, 0x00000281, +- 0x03F, 0x00000008, ++ 0x03F, 0x0000006D, + 0x033, 0x00000282, +- 0x03F, 0x0000000B, ++ 0x03F, 0x0000046A, + 0x033, 0x00000283, +- 0x03F, 0x0000000E, ++ 0x03F, 0x0000086A, + 0x033, 0x00000284, +- 0x03F, 0x0000002B, ++ 0x03F, 0x00000C89, + 0x033, 0x00000285, +- 0x03F, 0x0000002E, ++ 0x03F, 0x00000CE8, + 0x033, 0x00000286, +- 0x03F, 0x0000006B, ++ 0x03F, 0x00000CEB, + 0x033, 0x00000287, +- 0x03F, 0x0000006E, ++ 0x03F, 0x00000CEE, + 0x033, 0x00000288, +- 0x03F, 0x00000071, ++ 0x03F, 0x00000CF1, + 0x033, 0x00000289, +- 0x03F, 0x00000074, ++ 0x03F, 0x00000CF4, + 0x033, 0x0000028A, +- 0x03F, 0x00000077, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000CF7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000280, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000280, + 0x03F, 0x00000005, + 0x033, 0x00000281, +@@ -19996,7 +33811,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000074, + 0x033, 0x0000028A, + 0x03F, 0x00000077, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000280, + 0x03F, 0x00000005, + 0x033, 0x00000281, +@@ -20022,28 +33837,508 @@ static const u32 rtw8822c_rf_b[] = { + 0xA0000000, 0x00000000, + 0x033, 0x00000280, + 0x03F, 0x0000006A, +- 0x033, 0x00000281, ++ 0x033, 0x00000281, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000282, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000283, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000284, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000285, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000286, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000287, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000288, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000289, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000028A, ++ 0x03F, 0x00000CF7, ++ 0xB0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000301, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000304, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000305, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000031, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000034, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000053, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000056, ++ 0x033, 0x0000030A, ++ 0x03F, 0x000000D1, ++ 0x0EE, 0x00000000, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x00000005, ++ 0x033, 0x00000301, ++ 0x03F, 0x00000008, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000000B, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000000E, ++ 0x033, 0x00000304, ++ 0x03F, 0x0000002B, ++ 0x033, 0x00000305, ++ 0x03F, 0x0000002E, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000031, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000034, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000053, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000056, ++ 0x033, 0x0000030A, ++ 0x03F, 0x000000D1, ++ 0x0EE, 0x00000000, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, + 0x03F, 0x0000006D, +- 0x033, 0x00000282, ++ 0x033, 0x00000302, + 0x03F, 0x0000046A, +- 0x033, 0x00000283, ++ 0x033, 0x00000303, + 0x03F, 0x0000086A, +- 0x033, 0x00000284, ++ 0x033, 0x00000304, + 0x03F, 0x00000C89, +- 0x033, 0x00000285, ++ 0x033, 0x00000305, + 0x03F, 0x00000CE8, +- 0x033, 0x00000286, ++ 0x033, 0x00000306, + 0x03F, 0x00000CEB, +- 0x033, 0x00000287, ++ 0x033, 0x00000307, + 0x03F, 0x00000CEE, +- 0x033, 0x00000288, ++ 0x033, 0x00000308, + 0x03F, 0x00000CF1, +- 0x033, 0x00000289, ++ 0x033, 0x00000309, + 0x03F, 0x00000CF4, +- 0x033, 0x0000028A, ++ 0x033, 0x0000030A, + 0x03F, 0x00000CF7, +- 0xB0000000, 0x00000000, +- 0x83000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x0EE, 0x00000000, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -20067,7 +34362,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -20091,7 +34386,151 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000300, ++ 0x03F, 0x0000006A, ++ 0x033, 0x00000301, ++ 0x03F, 0x0000006D, ++ 0x033, 0x00000302, ++ 0x03F, 0x0000046A, ++ 0x033, 0x00000303, ++ 0x03F, 0x0000086A, ++ 0x033, 0x00000304, ++ 0x03F, 0x00000C89, ++ 0x033, 0x00000305, ++ 0x03F, 0x00000CE8, ++ 0x033, 0x00000306, ++ 0x03F, 0x00000CEB, ++ 0x033, 0x00000307, ++ 0x03F, 0x00000CEE, ++ 0x033, 0x00000308, ++ 0x03F, 0x00000CF1, ++ 0x033, 0x00000309, ++ 0x03F, 0x00000CF4, ++ 0x033, 0x0000030A, ++ 0x03F, 0x00000CF7, ++ 0x0EE, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -20115,7 +34554,7 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000030A, + 0x03F, 0x000000D1, + 0x0EE, 0x00000000, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000300, + 0x03F, 0x00000005, + 0x033, 0x00000301, +@@ -20165,7 +34604,11 @@ static const u32 rtw8822c_rf_b[] = { + 0x0EE, 0x00000000, + 0xB0000000, 0x00000000, + 0x051, 0x0003C800, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000942C0, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000942C0, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, +@@ -20183,6 +34626,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x052, 0x000902CA, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -20197,10 +34642,28 @@ static const u32 rtw8822c_rf_b[] = { + 0x052, 0x000902CA, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x052, 0x000902CA, + 0xA0000000, 0x00000000, + 0x052, 0x000942C0, + 0xB0000000, 0x00000000, +@@ -20209,150 +34672,202 @@ static const u32 rtw8822c_rf_b[] = { + 0x057, 0x0004C80A, + 0x0EF, 0x00000020, + 0x033, 0x00000000, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000241C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x0000C246, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000001, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000001, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -20370,6 +34885,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -20384,158 +34901,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000241C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x0000C246, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000004, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000004, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000005, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -20553,6 +35140,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -20567,158 +35156,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000241C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x0000C246, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000007, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000007, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000008, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0000C246, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -20736,6 +35395,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -20750,158 +35411,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000009, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000241C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x0000000A, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000000A, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000B, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -20919,6 +35650,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -20933,158 +35666,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000C, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000241C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x0000000D, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000000D, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000241C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000241C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -21102,6 +35905,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -21116,158 +35921,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002C246, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000F, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00024246, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00024246, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x00024246, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000010, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00024246, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00024246, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00024246, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000010, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000011, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, +@@ -21285,6 +36160,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -21299,158 +36176,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000012, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000013, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000013, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000014, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -21468,6 +36415,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -21482,158 +36431,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000015, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000016, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000016, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000017, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -21651,6 +36670,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -21665,158 +36686,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000018, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000019, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000019, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001A, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -21834,6 +36925,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -21848,158 +36941,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001B, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x0000001C, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001C, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001D, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -22017,6 +37180,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -22031,158 +37196,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001E, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x0000001F, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x0000001F, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000020, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -22200,6 +37435,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -22214,371 +37451,513 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000021, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000022, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000022, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000020, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xA0000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0002CA46, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0002CA46, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000024, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000024, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000025, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000025, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000026, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -22596,6 +37975,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -22610,158 +37991,228 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000027, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0xA0000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000020, +- 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x000209C6, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x033, 0x00000028, +- 0x83000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03E, 0x00000030, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, + 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000028, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, ++ 0x03F, 0x000209C6, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03E, 0x00000030, + 0x03F, 0x000209C6, + 0xA0000000, 0x00000000, ++ 0x03E, 0x00000020, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000029, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -22779,6 +38230,8 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000016, 0x00000000, 0x40000000, 0x00000000, +@@ -22793,16 +38246,38 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x0002CA46, + 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000002A, + 0x03E, 0x00000020, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, +@@ -22819,123 +38294,419 @@ static const u32 rtw8822c_rf_b[] = { + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, ++ 0x03F, 0x0001CA46, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x0001CA46, ++ 0xA0000000, 0x00000000, ++ 0x03F, 0x00008E46, ++ 0xB0000000, 0x00000000, ++ 0x0EF, 0x00000000, ++ 0x0EE, 0x00010000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000468, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000868, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000909, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000D0A, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000D4A, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000D8B, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DF7, ++ 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000060, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000061, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000062, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000063, ++ 0x03F, 0x00000CC6, ++ 0x033, 0x00000064, ++ 0x03F, 0x00000CC9, ++ 0x033, 0x00000065, ++ 0x03F, 0x00000CCC, ++ 0x033, 0x00000066, ++ 0x03F, 0x00000CCF, ++ 0x033, 0x00000067, ++ 0x03F, 0x00000CD2, ++ 0x033, 0x00000068, ++ 0x03F, 0x00000CD5, ++ 0x033, 0x00000069, ++ 0x03F, 0x00000DD4, ++ 0x033, 0x0000006A, ++ 0x03F, 0x00000DD7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, +- 0x03F, 0x0001CA46, +- 0xA0000000, 0x00000000, +- 0x03F, 0x00008E46, +- 0xB0000000, 0x00000000, +- 0x0EF, 0x00000000, +- 0x0EE, 0x00010000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x91000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x93000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x92000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x92000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, +- 0x03F, 0x00000468, ++ 0x03F, 0x00000467, + 0x033, 0x00000061, +- 0x03F, 0x00000868, ++ 0x03F, 0x00000867, + 0x033, 0x00000062, +- 0x03F, 0x00000909, ++ 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D0A, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D4A, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8B, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -22943,22 +38714,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -22966,22 +38737,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -22989,22 +38760,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23012,22 +38783,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23035,22 +38806,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x94000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23058,22 +38829,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x93000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23081,22 +38852,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23104,22 +38875,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23127,22 +38898,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23150,22 +38921,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23173,22 +38944,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23196,22 +38967,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23219,22 +38990,22 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, +- 0x94000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x03F, 0x00000DD7, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000467, + 0x033, 0x00000061, +@@ -23242,21 +39013,21 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000062, + 0x03F, 0x00000908, + 0x033, 0x00000063, +- 0x03F, 0x00000D09, ++ 0x03F, 0x00000CC6, + 0x033, 0x00000064, +- 0x03F, 0x00000D49, ++ 0x03F, 0x00000CC9, + 0x033, 0x00000065, +- 0x03F, 0x00000D8A, ++ 0x03F, 0x00000CCC, + 0x033, 0x00000066, +- 0x03F, 0x00000DEB, ++ 0x03F, 0x00000CCF, + 0x033, 0x00000067, +- 0x03F, 0x00000DEE, ++ 0x03F, 0x00000CD2, + 0x033, 0x00000068, +- 0x03F, 0x00000DF1, ++ 0x03F, 0x00000CD5, + 0x033, 0x00000069, +- 0x03F, 0x00000DF4, ++ 0x03F, 0x00000DD4, + 0x033, 0x0000006A, +- 0x03F, 0x00000DF7, ++ 0x03F, 0x00000DD7, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000487, +@@ -23281,7 +39052,53 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, +- 0x81000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x8f000000, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x9f000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000487, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000887, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000947, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D48, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D88, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000DE8, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x91000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, +@@ -23488,6 +39305,29 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, ++ 0x93000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, + 0x93000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, +@@ -23649,6 +39489,29 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, ++ 0x94000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, + 0x94000015, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000467, +@@ -23695,6 +39558,190 @@ static const u32 rtw8822c_rf_b[] = { + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, ++ 0x95000001, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000002, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000003, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000004, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000005, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000006, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000015, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, ++ 0x95000016, 0x00000000, 0x40000000, 0x00000000, ++ 0x033, 0x00000020, ++ 0x03F, 0x00000467, ++ 0x033, 0x00000021, ++ 0x03F, 0x00000867, ++ 0x033, 0x00000022, ++ 0x03F, 0x00000908, ++ 0x033, 0x00000023, ++ 0x03F, 0x00000D09, ++ 0x033, 0x00000024, ++ 0x03F, 0x00000D49, ++ 0x033, 0x00000025, ++ 0x03F, 0x00000D8A, ++ 0x033, 0x00000026, ++ 0x03F, 0x00000DEB, ++ 0x033, 0x00000027, ++ 0x03F, 0x00000DEE, ++ 0x033, 0x00000028, ++ 0x03F, 0x00000DF1, ++ 0x033, 0x00000029, ++ 0x03F, 0x00000DF4, ++ 0x033, 0x0000002A, ++ 0x03F, 0x00000DF7, + 0xA0000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000487, +@@ -23770,10 +39817,6 @@ static const u32 rtw8822c_rf_b[] = { + 0x033, 0x00000007, + 0x03F, 0x00000002, + 0x0EF, 0x00000000, +- 0x0EF, 0x00080000, +- 0x033, 0x00000001, +- 0x03F, 0x000916BF, +- 0x0EF, 0x00000000, + }; + + RTW_DECL_TABLE_RF_RADIO(rtw8822c_rf_b, B); +@@ -24820,7 +40863,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 0, 1, 144, 76, }, + { 9, 1, 0, 1, 144, 127, }, + { 0, 1, 0, 1, 149, 76, }, +- { 2, 1, 0, 1, 149, -128, }, ++ { 2, 1, 0, 1, 149, 54, }, + { 1, 1, 0, 1, 149, 127, }, + { 3, 1, 0, 1, 149, 76, }, + { 4, 1, 0, 1, 149, 74, }, +@@ -24828,9 +40871,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 1, 149, 76, }, + { 7, 1, 0, 1, 149, 54, }, + { 8, 1, 0, 1, 149, 76, }, +- { 9, 1, 0, 1, 149, -128, }, ++ { 9, 1, 0, 1, 149, 54, }, + { 0, 1, 0, 1, 153, 76, }, +- { 2, 1, 0, 1, 153, -128, }, ++ { 2, 1, 0, 1, 153, 54, }, + { 1, 1, 0, 1, 153, 127, }, + { 3, 1, 0, 1, 153, 76, }, + { 4, 1, 0, 1, 153, 74, }, +@@ -24838,9 +40881,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 1, 153, 76, }, + { 7, 1, 0, 1, 153, 54, }, + { 8, 1, 0, 1, 153, 76, }, +- { 9, 1, 0, 1, 153, -128, }, ++ { 9, 1, 0, 1, 153, 54, }, + { 0, 1, 0, 1, 157, 76, }, +- { 2, 1, 0, 1, 157, -128, }, ++ { 2, 1, 0, 1, 157, 54, }, + { 1, 1, 0, 1, 157, 127, }, + { 3, 1, 0, 1, 157, 76, }, + { 4, 1, 0, 1, 157, 74, }, +@@ -24848,9 +40891,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 1, 157, 76, }, + { 7, 1, 0, 1, 157, 54, }, + { 8, 1, 0, 1, 157, 76, }, +- { 9, 1, 0, 1, 157, -128, }, ++ { 9, 1, 0, 1, 157, 54, }, + { 0, 1, 0, 1, 161, 76, }, +- { 2, 1, 0, 1, 161, -128, }, ++ { 2, 1, 0, 1, 161, 54, }, + { 1, 1, 0, 1, 161, 127, }, + { 3, 1, 0, 1, 161, 76, }, + { 4, 1, 0, 1, 161, 74, }, +@@ -24858,9 +40901,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 1, 161, 76, }, + { 7, 1, 0, 1, 161, 54, }, + { 8, 1, 0, 1, 161, 76, }, +- { 9, 1, 0, 1, 161, -128, }, ++ { 9, 1, 0, 1, 161, 54, }, + { 0, 1, 0, 1, 165, 76, }, +- { 2, 1, 0, 1, 165, -128, }, ++ { 2, 1, 0, 1, 165, 54, }, + { 1, 1, 0, 1, 165, 127, }, + { 3, 1, 0, 1, 165, 76, }, + { 4, 1, 0, 1, 165, 74, }, +@@ -24868,7 +40911,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 1, 165, 76, }, + { 7, 1, 0, 1, 165, 54, }, + { 8, 1, 0, 1, 165, 76, }, +- { 9, 1, 0, 1, 165, -128, }, ++ { 9, 1, 0, 1, 165, 54, }, + { 0, 1, 0, 2, 36, 72, }, + { 2, 1, 0, 2, 36, 62, }, + { 1, 1, 0, 2, 36, 62, }, +@@ -25070,7 +41113,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 0, 2, 144, 76, }, + { 9, 1, 0, 2, 144, 127, }, + { 0, 1, 0, 2, 149, 76, }, +- { 2, 1, 0, 2, 149, -128, }, ++ { 2, 1, 0, 2, 149, 54, }, + { 1, 1, 0, 2, 149, 127, }, + { 3, 1, 0, 2, 149, 76, }, + { 4, 1, 0, 2, 149, 74, }, +@@ -25078,9 +41121,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 2, 149, 76, }, + { 7, 1, 0, 2, 149, 54, }, + { 8, 1, 0, 2, 149, 76, }, +- { 9, 1, 0, 2, 149, -128, }, ++ { 9, 1, 0, 2, 149, 54, }, + { 0, 1, 0, 2, 153, 76, }, +- { 2, 1, 0, 2, 153, -128, }, ++ { 2, 1, 0, 2, 153, 54, }, + { 1, 1, 0, 2, 153, 127, }, + { 3, 1, 0, 2, 153, 76, }, + { 4, 1, 0, 2, 153, 74, }, +@@ -25088,9 +41131,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 2, 153, 76, }, + { 7, 1, 0, 2, 153, 54, }, + { 8, 1, 0, 2, 153, 76, }, +- { 9, 1, 0, 2, 153, -128, }, ++ { 9, 1, 0, 2, 153, 54, }, + { 0, 1, 0, 2, 157, 76, }, +- { 2, 1, 0, 2, 157, -128, }, ++ { 2, 1, 0, 2, 157, 54, }, + { 1, 1, 0, 2, 157, 127, }, + { 3, 1, 0, 2, 157, 76, }, + { 4, 1, 0, 2, 157, 74, }, +@@ -25098,9 +41141,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 2, 157, 76, }, + { 7, 1, 0, 2, 157, 54, }, + { 8, 1, 0, 2, 157, 76, }, +- { 9, 1, 0, 2, 157, -128, }, ++ { 9, 1, 0, 2, 157, 54, }, + { 0, 1, 0, 2, 161, 76, }, +- { 2, 1, 0, 2, 161, -128, }, ++ { 2, 1, 0, 2, 161, 54, }, + { 1, 1, 0, 2, 161, 127, }, + { 3, 1, 0, 2, 161, 76, }, + { 4, 1, 0, 2, 161, 74, }, +@@ -25108,9 +41151,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 2, 161, 76, }, + { 7, 1, 0, 2, 161, 54, }, + { 8, 1, 0, 2, 161, 76, }, +- { 9, 1, 0, 2, 161, -128, }, ++ { 9, 1, 0, 2, 161, 54, }, + { 0, 1, 0, 2, 165, 76, }, +- { 2, 1, 0, 2, 165, -128, }, ++ { 2, 1, 0, 2, 165, 54, }, + { 1, 1, 0, 2, 165, 127, }, + { 3, 1, 0, 2, 165, 76, }, + { 4, 1, 0, 2, 165, 74, }, +@@ -25118,7 +41161,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 2, 165, 76, }, + { 7, 1, 0, 2, 165, 54, }, + { 8, 1, 0, 2, 165, 76, }, +- { 9, 1, 0, 2, 165, -128, }, ++ { 9, 1, 0, 2, 165, 54, }, + { 0, 1, 0, 3, 36, 68, }, + { 2, 1, 0, 3, 36, 38, }, + { 1, 1, 0, 3, 36, 50, }, +@@ -25320,7 +41363,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 0, 3, 144, 68, }, + { 9, 1, 0, 3, 144, 127, }, + { 0, 1, 0, 3, 149, 76, }, +- { 2, 1, 0, 3, 149, -128, }, ++ { 2, 1, 0, 3, 149, 30, }, + { 1, 1, 0, 3, 149, 127, }, + { 3, 1, 0, 3, 149, 76, }, + { 4, 1, 0, 3, 149, 60, }, +@@ -25328,9 +41371,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 3, 149, 76, }, + { 7, 1, 0, 3, 149, 30, }, + { 8, 1, 0, 3, 149, 72, }, +- { 9, 1, 0, 3, 149, -128, }, ++ { 9, 1, 0, 3, 149, 30, }, + { 0, 1, 0, 3, 153, 76, }, +- { 2, 1, 0, 3, 153, -128, }, ++ { 2, 1, 0, 3, 153, 30, }, + { 1, 1, 0, 3, 153, 127, }, + { 3, 1, 0, 3, 153, 76, }, + { 4, 1, 0, 3, 153, 60, }, +@@ -25338,9 +41381,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 3, 153, 76, }, + { 7, 1, 0, 3, 153, 30, }, + { 8, 1, 0, 3, 153, 76, }, +- { 9, 1, 0, 3, 153, -128, }, ++ { 9, 1, 0, 3, 153, 30, }, + { 0, 1, 0, 3, 157, 76, }, +- { 2, 1, 0, 3, 157, -128, }, ++ { 2, 1, 0, 3, 157, 30, }, + { 1, 1, 0, 3, 157, 127, }, + { 3, 1, 0, 3, 157, 76, }, + { 4, 1, 0, 3, 157, 60, }, +@@ -25348,9 +41391,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 3, 157, 76, }, + { 7, 1, 0, 3, 157, 30, }, + { 8, 1, 0, 3, 157, 76, }, +- { 9, 1, 0, 3, 157, -128, }, ++ { 9, 1, 0, 3, 157, 30, }, + { 0, 1, 0, 3, 161, 76, }, +- { 2, 1, 0, 3, 161, -128, }, ++ { 2, 1, 0, 3, 161, 30, }, + { 1, 1, 0, 3, 161, 127, }, + { 3, 1, 0, 3, 161, 76, }, + { 4, 1, 0, 3, 161, 60, }, +@@ -25358,9 +41401,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 3, 161, 76, }, + { 7, 1, 0, 3, 161, 30, }, + { 8, 1, 0, 3, 161, 76, }, +- { 9, 1, 0, 3, 161, -128, }, ++ { 9, 1, 0, 3, 161, 30, }, + { 0, 1, 0, 3, 165, 76, }, +- { 2, 1, 0, 3, 165, -128, }, ++ { 2, 1, 0, 3, 165, 30, }, + { 1, 1, 0, 3, 165, 127, }, + { 3, 1, 0, 3, 165, 76, }, + { 4, 1, 0, 3, 165, 60, }, +@@ -25368,7 +41411,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 0, 3, 165, 76, }, + { 7, 1, 0, 3, 165, 30, }, + { 8, 1, 0, 3, 165, 76, }, +- { 9, 1, 0, 3, 165, -128, }, ++ { 9, 1, 0, 3, 165, 30, }, + { 0, 1, 1, 2, 38, 66, }, + { 2, 1, 1, 2, 38, 64, }, + { 1, 1, 1, 2, 38, 62, }, +@@ -25470,7 +41513,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 1, 2, 142, 72, }, + { 9, 1, 1, 2, 142, 127, }, + { 0, 1, 1, 2, 151, 72, }, +- { 2, 1, 1, 2, 151, -128, }, ++ { 2, 1, 1, 2, 151, 54, }, + { 1, 1, 1, 2, 151, 127, }, + { 3, 1, 1, 2, 151, 72, }, + { 4, 1, 1, 2, 151, 72, }, +@@ -25478,9 +41521,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 1, 2, 151, 72, }, + { 7, 1, 1, 2, 151, 54, }, + { 8, 1, 1, 2, 151, 72, }, +- { 9, 1, 1, 2, 151, -128, }, ++ { 9, 1, 1, 2, 151, 54, }, + { 0, 1, 1, 2, 159, 72, }, +- { 2, 1, 1, 2, 159, -128, }, ++ { 2, 1, 1, 2, 159, 54, }, + { 1, 1, 1, 2, 159, 127, }, + { 3, 1, 1, 2, 159, 72, }, + { 4, 1, 1, 2, 159, 72, }, +@@ -25488,7 +41531,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 1, 2, 159, 72, }, + { 7, 1, 1, 2, 159, 54, }, + { 8, 1, 1, 2, 159, 72, }, +- { 9, 1, 1, 2, 159, -128, }, ++ { 9, 1, 1, 2, 159, 54, }, + { 0, 1, 1, 3, 38, 60, }, + { 2, 1, 1, 3, 38, 40, }, + { 1, 1, 1, 3, 38, 50, }, +@@ -25590,7 +41633,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 1, 3, 142, 68, }, + { 9, 1, 1, 3, 142, 127, }, + { 0, 1, 1, 3, 151, 72, }, +- { 2, 1, 1, 3, 151, -128, }, ++ { 2, 1, 1, 3, 151, 30, }, + { 1, 1, 1, 3, 151, 127, }, + { 3, 1, 1, 3, 151, 72, }, + { 4, 1, 1, 3, 151, 66, }, +@@ -25598,9 +41641,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 1, 3, 151, 72, }, + { 7, 1, 1, 3, 151, 30, }, + { 8, 1, 1, 3, 151, 68, }, +- { 9, 1, 1, 3, 151, -128, }, ++ { 9, 1, 1, 3, 151, 30, }, + { 0, 1, 1, 3, 159, 72, }, +- { 2, 1, 1, 3, 159, -128, }, ++ { 2, 1, 1, 3, 159, 30, }, + { 1, 1, 1, 3, 159, 127, }, + { 3, 1, 1, 3, 159, 72, }, + { 4, 1, 1, 3, 159, 66, }, +@@ -25608,7 +41651,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 1, 3, 159, 72, }, + { 7, 1, 1, 3, 159, 30, }, + { 8, 1, 1, 3, 159, 72, }, +- { 9, 1, 1, 3, 159, -128, }, ++ { 9, 1, 1, 3, 159, 30, }, + { 0, 1, 2, 4, 42, 64, }, + { 2, 1, 2, 4, 42, 64, }, + { 1, 1, 2, 4, 42, 64, }, +@@ -25660,7 +41703,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 2, 4, 138, 72, }, + { 9, 1, 2, 4, 138, 127, }, + { 0, 1, 2, 4, 155, 72, }, +- { 2, 1, 2, 4, 155, -128, }, ++ { 2, 1, 2, 4, 155, 54, }, + { 1, 1, 2, 4, 155, 127, }, + { 3, 1, 2, 4, 155, 72, }, + { 4, 1, 2, 4, 155, 68, }, +@@ -25668,7 +41711,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 2, 4, 155, 72, }, + { 7, 1, 2, 4, 155, 54, }, + { 8, 1, 2, 4, 155, 68, }, +- { 9, 1, 2, 4, 155, -128, }, ++ { 9, 1, 2, 4, 155, 54, }, + { 0, 1, 2, 5, 42, 54, }, + { 2, 1, 2, 5, 42, 40, }, + { 1, 1, 2, 5, 42, 50, }, +@@ -25720,7 +41763,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 8, 1, 2, 5, 138, 66, }, + { 9, 1, 2, 5, 138, 127, }, + { 0, 1, 2, 5, 155, 62, }, +- { 2, 1, 2, 5, 155, -128, }, ++ { 2, 1, 2, 5, 155, 30, }, + { 1, 1, 2, 5, 155, 127, }, + { 3, 1, 2, 5, 155, 62, }, + { 4, 1, 2, 5, 155, 58, }, +@@ -25728,145 +41771,145 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 6, 1, 2, 5, 155, 62, }, + { 7, 1, 2, 5, 155, 30, }, + { 8, 1, 2, 5, 155, 62, }, +- { 9, 1, 2, 5, 155, -128, }, ++ { 9, 1, 2, 5, 155, 30, }, + }; + + RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type0); + + static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 0, 0, 0, 0, 1, 72, }, +- { 2, 0, 0, 0, 1, 60, }, +- { 1, 0, 0, 0, 1, 68, }, ++ { 2, 0, 0, 0, 1, 56, }, ++ { 1, 0, 0, 0, 1, 72, }, + { 3, 0, 0, 0, 1, 72, }, + { 4, 0, 0, 0, 1, 76, }, +- { 5, 0, 0, 0, 1, 60, }, ++ { 5, 0, 0, 0, 1, 56, }, + { 6, 0, 0, 0, 1, 72, }, + { 7, 0, 0, 0, 1, 60, }, + { 8, 0, 0, 0, 1, 72, }, + { 9, 0, 0, 0, 1, 60, }, + { 0, 0, 0, 0, 2, 72, }, +- { 2, 0, 0, 0, 2, 60, }, +- { 1, 0, 0, 0, 2, 68, }, ++ { 2, 0, 0, 0, 2, 56, }, ++ { 1, 0, 0, 0, 2, 72, }, + { 3, 0, 0, 0, 2, 72, }, + { 4, 0, 0, 0, 2, 76, }, +- { 5, 0, 0, 0, 2, 60, }, ++ { 5, 0, 0, 0, 2, 56, }, + { 6, 0, 0, 0, 2, 72, }, + { 7, 0, 0, 0, 2, 60, }, + { 8, 0, 0, 0, 2, 72, }, + { 9, 0, 0, 0, 2, 60, }, + { 0, 0, 0, 0, 3, 76, }, +- { 2, 0, 0, 0, 3, 60, }, +- { 1, 0, 0, 0, 3, 68, }, ++ { 2, 0, 0, 0, 3, 56, }, ++ { 1, 0, 0, 0, 3, 72, }, + { 3, 0, 0, 0, 3, 76, }, + { 4, 0, 0, 0, 3, 76, }, +- { 5, 0, 0, 0, 3, 60, }, ++ { 5, 0, 0, 0, 3, 56, }, + { 6, 0, 0, 0, 3, 76, }, + { 7, 0, 0, 0, 3, 60, }, + { 8, 0, 0, 0, 3, 76, }, + { 9, 0, 0, 0, 3, 60, }, + { 0, 0, 0, 0, 4, 76, }, +- { 2, 0, 0, 0, 4, 60, }, +- { 1, 0, 0, 0, 4, 68, }, ++ { 2, 0, 0, 0, 4, 56, }, ++ { 1, 0, 0, 0, 4, 72, }, + { 3, 0, 0, 0, 4, 76, }, + { 4, 0, 0, 0, 4, 76, }, +- { 5, 0, 0, 0, 4, 60, }, ++ { 5, 0, 0, 0, 4, 56, }, + { 6, 0, 0, 0, 4, 76, }, + { 7, 0, 0, 0, 4, 60, }, + { 8, 0, 0, 0, 4, 76, }, + { 9, 0, 0, 0, 4, 60, }, + { 0, 0, 0, 0, 5, 76, }, +- { 2, 0, 0, 0, 5, 60, }, +- { 1, 0, 0, 0, 5, 68, }, ++ { 2, 0, 0, 0, 5, 56, }, ++ { 1, 0, 0, 0, 5, 72, }, + { 3, 0, 0, 0, 5, 76, }, + { 4, 0, 0, 0, 5, 76, }, +- { 5, 0, 0, 0, 5, 60, }, ++ { 5, 0, 0, 0, 5, 56, }, + { 6, 0, 0, 0, 5, 76, }, + { 7, 0, 0, 0, 5, 60, }, + { 8, 0, 0, 0, 5, 76, }, + { 9, 0, 0, 0, 5, 60, }, + { 0, 0, 0, 0, 6, 76, }, +- { 2, 0, 0, 0, 6, 60, }, +- { 1, 0, 0, 0, 6, 68, }, ++ { 2, 0, 0, 0, 6, 56, }, ++ { 1, 0, 0, 0, 6, 72, }, + { 3, 0, 0, 0, 6, 76, }, + { 4, 0, 0, 0, 6, 76, }, +- { 5, 0, 0, 0, 6, 60, }, ++ { 5, 0, 0, 0, 6, 56, }, + { 6, 0, 0, 0, 6, 76, }, + { 7, 0, 0, 0, 6, 60, }, + { 8, 0, 0, 0, 6, 76, }, + { 9, 0, 0, 0, 6, 60, }, + { 0, 0, 0, 0, 7, 76, }, +- { 2, 0, 0, 0, 7, 60, }, +- { 1, 0, 0, 0, 7, 68, }, ++ { 2, 0, 0, 0, 7, 56, }, ++ { 1, 0, 0, 0, 7, 72, }, + { 3, 0, 0, 0, 7, 76, }, + { 4, 0, 0, 0, 7, 76, }, +- { 5, 0, 0, 0, 7, 60, }, ++ { 5, 0, 0, 0, 7, 56, }, + { 6, 0, 0, 0, 7, 76, }, + { 7, 0, 0, 0, 7, 60, }, + { 8, 0, 0, 0, 7, 76, }, + { 9, 0, 0, 0, 7, 60, }, + { 0, 0, 0, 0, 8, 76, }, +- { 2, 0, 0, 0, 8, 60, }, +- { 1, 0, 0, 0, 8, 68, }, ++ { 2, 0, 0, 0, 8, 56, }, ++ { 1, 0, 0, 0, 8, 72, }, + { 3, 0, 0, 0, 8, 76, }, + { 4, 0, 0, 0, 8, 76, }, +- { 5, 0, 0, 0, 8, 60, }, ++ { 5, 0, 0, 0, 8, 56, }, + { 6, 0, 0, 0, 8, 76, }, + { 7, 0, 0, 0, 8, 60, }, + { 8, 0, 0, 0, 8, 76, }, + { 9, 0, 0, 0, 8, 60, }, + { 0, 0, 0, 0, 9, 76, }, +- { 2, 0, 0, 0, 9, 60, }, +- { 1, 0, 0, 0, 9, 68, }, ++ { 2, 0, 0, 0, 9, 56, }, ++ { 1, 0, 0, 0, 9, 72, }, + { 3, 0, 0, 0, 9, 76, }, + { 4, 0, 0, 0, 9, 76, }, +- { 5, 0, 0, 0, 9, 60, }, ++ { 5, 0, 0, 0, 9, 56, }, + { 6, 0, 0, 0, 9, 76, }, + { 7, 0, 0, 0, 9, 60, }, + { 8, 0, 0, 0, 9, 76, }, + { 9, 0, 0, 0, 9, 60, }, + { 0, 0, 0, 0, 10, 72, }, +- { 2, 0, 0, 0, 10, 60, }, +- { 1, 0, 0, 0, 10, 68, }, ++ { 2, 0, 0, 0, 10, 56, }, ++ { 1, 0, 0, 0, 10, 72, }, + { 3, 0, 0, 0, 10, 72, }, + { 4, 0, 0, 0, 10, 76, }, +- { 5, 0, 0, 0, 10, 60, }, ++ { 5, 0, 0, 0, 10, 56, }, + { 6, 0, 0, 0, 10, 72, }, + { 7, 0, 0, 0, 10, 60, }, + { 8, 0, 0, 0, 10, 72, }, + { 9, 0, 0, 0, 10, 60, }, + { 0, 0, 0, 0, 11, 72, }, +- { 2, 0, 0, 0, 11, 60, }, +- { 1, 0, 0, 0, 11, 68, }, ++ { 2, 0, 0, 0, 11, 56, }, ++ { 1, 0, 0, 0, 11, 72, }, + { 3, 0, 0, 0, 11, 72, }, + { 4, 0, 0, 0, 11, 76, }, +- { 5, 0, 0, 0, 11, 60, }, ++ { 5, 0, 0, 0, 11, 56, }, + { 6, 0, 0, 0, 11, 72, }, + { 7, 0, 0, 0, 11, 60, }, + { 8, 0, 0, 0, 11, 72, }, + { 9, 0, 0, 0, 11, 60, }, + { 0, 0, 0, 0, 12, 44, }, +- { 2, 0, 0, 0, 12, 60, }, +- { 1, 0, 0, 0, 12, 68, }, ++ { 2, 0, 0, 0, 12, 56, }, ++ { 1, 0, 0, 0, 12, 72, }, + { 3, 0, 0, 0, 12, 52, }, + { 4, 0, 0, 0, 12, 76, }, +- { 5, 0, 0, 0, 12, 60, }, ++ { 5, 0, 0, 0, 12, 56, }, + { 6, 0, 0, 0, 12, 52, }, + { 7, 0, 0, 0, 12, 60, }, + { 8, 0, 0, 0, 12, 52, }, + { 9, 0, 0, 0, 12, 60, }, + { 0, 0, 0, 0, 13, 40, }, +- { 2, 0, 0, 0, 13, 60, }, +- { 1, 0, 0, 0, 13, 68, }, ++ { 2, 0, 0, 0, 13, 56, }, ++ { 1, 0, 0, 0, 13, 72, }, + { 3, 0, 0, 0, 13, 48, }, + { 4, 0, 0, 0, 13, 76, }, +- { 5, 0, 0, 0, 13, 60, }, ++ { 5, 0, 0, 0, 13, 56, }, + { 6, 0, 0, 0, 13, 48, }, + { 7, 0, 0, 0, 13, 60, }, + { 8, 0, 0, 0, 13, 48, }, + { 9, 0, 0, 0, 13, 60, }, + { 0, 0, 0, 0, 14, 127, }, + { 2, 0, 0, 0, 14, 127, }, +- { 1, 0, 0, 0, 14, 68, }, ++ { 1, 0, 0, 0, 14, 72, }, + { 3, 0, 0, 0, 14, 127, }, + { 4, 0, 0, 0, 14, 127, }, + { 5, 0, 0, 0, 14, 127, }, +@@ -25998,7 +42041,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 1, 13, 60, }, + { 1, 0, 0, 1, 13, 76, }, + { 3, 0, 0, 1, 13, 28, }, +- { 4, 0, 0, 1, 13, 70, }, ++ { 4, 0, 0, 1, 13, 74, }, + { 5, 0, 0, 1, 13, 60, }, + { 6, 0, 0, 1, 13, 28, }, + { 7, 0, 0, 1, 13, 60, }, +@@ -26138,7 +42181,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 2, 13, 60, }, + { 1, 0, 0, 2, 13, 76, }, + { 3, 0, 0, 2, 13, 28, }, +- { 4, 0, 0, 2, 13, 72, }, ++ { 4, 0, 0, 2, 13, 74, }, + { 5, 0, 0, 2, 13, 60, }, + { 6, 0, 0, 2, 13, 28, }, + { 7, 0, 0, 2, 13, 60, }, +@@ -26158,7 +42201,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 1, 36, }, + { 1, 0, 0, 3, 1, 66, }, + { 3, 0, 0, 3, 1, 52, }, +- { 4, 0, 0, 3, 1, 68, }, ++ { 4, 0, 0, 3, 1, 72, }, + { 5, 0, 0, 3, 1, 36, }, + { 6, 0, 0, 3, 1, 52, }, + { 7, 0, 0, 3, 1, 36, }, +@@ -26168,7 +42211,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 2, 36, }, + { 1, 0, 0, 3, 2, 66, }, + { 3, 0, 0, 3, 2, 60, }, +- { 4, 0, 0, 3, 2, 70, }, ++ { 4, 0, 0, 3, 2, 72, }, + { 5, 0, 0, 3, 2, 36, }, + { 6, 0, 0, 3, 2, 60, }, + { 7, 0, 0, 3, 2, 36, }, +@@ -26178,7 +42221,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 3, 36, }, + { 1, 0, 0, 3, 3, 66, }, + { 3, 0, 0, 3, 3, 64, }, +- { 4, 0, 0, 3, 3, 70, }, ++ { 4, 0, 0, 3, 3, 72, }, + { 5, 0, 0, 3, 3, 36, }, + { 6, 0, 0, 3, 3, 64, }, + { 7, 0, 0, 3, 3, 36, }, +@@ -26188,7 +42231,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 4, 36, }, + { 1, 0, 0, 3, 4, 66, }, + { 3, 0, 0, 3, 4, 68, }, +- { 4, 0, 0, 3, 4, 70, }, ++ { 4, 0, 0, 3, 4, 72, }, + { 5, 0, 0, 3, 4, 36, }, + { 6, 0, 0, 3, 4, 68, }, + { 7, 0, 0, 3, 4, 36, }, +@@ -26198,7 +42241,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 5, 36, }, + { 1, 0, 0, 3, 5, 66, }, + { 3, 0, 0, 3, 5, 76, }, +- { 4, 0, 0, 3, 5, 70, }, ++ { 4, 0, 0, 3, 5, 72, }, + { 5, 0, 0, 3, 5, 36, }, + { 6, 0, 0, 3, 5, 76, }, + { 7, 0, 0, 3, 5, 36, }, +@@ -26208,7 +42251,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 6, 36, }, + { 1, 0, 0, 3, 6, 66, }, + { 3, 0, 0, 3, 6, 76, }, +- { 4, 0, 0, 3, 6, 70, }, ++ { 4, 0, 0, 3, 6, 72, }, + { 5, 0, 0, 3, 6, 36, }, + { 6, 0, 0, 3, 6, 76, }, + { 7, 0, 0, 3, 6, 36, }, +@@ -26218,7 +42261,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 7, 36, }, + { 1, 0, 0, 3, 7, 66, }, + { 3, 0, 0, 3, 7, 76, }, +- { 4, 0, 0, 3, 7, 70, }, ++ { 4, 0, 0, 3, 7, 72, }, + { 5, 0, 0, 3, 7, 36, }, + { 6, 0, 0, 3, 7, 76, }, + { 7, 0, 0, 3, 7, 36, }, +@@ -26228,7 +42271,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 8, 36, }, + { 1, 0, 0, 3, 8, 66, }, + { 3, 0, 0, 3, 8, 68, }, +- { 4, 0, 0, 3, 8, 70, }, ++ { 4, 0, 0, 3, 8, 72, }, + { 5, 0, 0, 3, 8, 36, }, + { 6, 0, 0, 3, 8, 68, }, + { 7, 0, 0, 3, 8, 36, }, +@@ -26238,7 +42281,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 9, 36, }, + { 1, 0, 0, 3, 9, 66, }, + { 3, 0, 0, 3, 9, 64, }, +- { 4, 0, 0, 3, 9, 70, }, ++ { 4, 0, 0, 3, 9, 72, }, + { 5, 0, 0, 3, 9, 36, }, + { 6, 0, 0, 3, 9, 64, }, + { 7, 0, 0, 3, 9, 36, }, +@@ -26248,7 +42291,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 10, 36, }, + { 1, 0, 0, 3, 10, 66, }, + { 3, 0, 0, 3, 10, 60, }, +- { 4, 0, 0, 3, 10, 70, }, ++ { 4, 0, 0, 3, 10, 72, }, + { 5, 0, 0, 3, 10, 36, }, + { 6, 0, 0, 3, 10, 60, }, + { 7, 0, 0, 3, 10, 36, }, +@@ -26258,7 +42301,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 11, 36, }, + { 1, 0, 0, 3, 11, 66, }, + { 3, 0, 0, 3, 11, 52, }, +- { 4, 0, 0, 3, 11, 70, }, ++ { 4, 0, 0, 3, 11, 72, }, + { 5, 0, 0, 3, 11, 36, }, + { 6, 0, 0, 3, 11, 52, }, + { 7, 0, 0, 3, 11, 36, }, +@@ -26268,7 +42311,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 12, 36, }, + { 1, 0, 0, 3, 12, 66, }, + { 3, 0, 0, 3, 12, 40, }, +- { 4, 0, 0, 3, 12, 70, }, ++ { 4, 0, 0, 3, 12, 72, }, + { 5, 0, 0, 3, 12, 36, }, + { 6, 0, 0, 3, 12, 40, }, + { 7, 0, 0, 3, 12, 36, }, +@@ -26278,7 +42321,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 0, 3, 13, 36, }, + { 1, 0, 0, 3, 13, 66, }, + { 3, 0, 0, 3, 13, 28, }, +- { 4, 0, 0, 3, 13, 62, }, ++ { 4, 0, 0, 3, 13, 68, }, + { 5, 0, 0, 3, 13, 36, }, + { 6, 0, 0, 3, 13, 28, }, + { 7, 0, 0, 3, 13, 36, }, +@@ -26458,7 +42501,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 0, 1, 3, 3, 36, }, + { 1, 0, 1, 3, 3, 66, }, + { 3, 0, 1, 3, 3, 48, }, +- { 4, 0, 1, 3, 3, 66, }, ++ { 4, 0, 1, 3, 3, 68, }, + { 5, 0, 1, 3, 3, 36, }, + { 6, 0, 1, 3, 3, 48, }, + { 7, 0, 1, 3, 3, 36, }, +@@ -26575,137 +42618,137 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 0, 1, 3, 14, 127, }, + { 9, 0, 1, 3, 14, 127, }, + { 0, 1, 0, 1, 36, 74, }, +- { 2, 1, 0, 1, 36, 62, }, +- { 1, 1, 0, 1, 36, 60, }, ++ { 2, 1, 0, 1, 36, 58, }, ++ { 1, 1, 0, 1, 36, 62, }, + { 3, 1, 0, 1, 36, 62, }, +- { 4, 1, 0, 1, 36, 76, }, +- { 5, 1, 0, 1, 36, 62, }, ++ { 4, 1, 0, 1, 36, 74, }, ++ { 5, 1, 0, 1, 36, 58, }, + { 6, 1, 0, 1, 36, 64, }, + { 7, 1, 0, 1, 36, 54, }, + { 8, 1, 0, 1, 36, 62, }, + { 9, 1, 0, 1, 36, 62, }, + { 0, 1, 0, 1, 40, 76, }, +- { 2, 1, 0, 1, 40, 62, }, ++ { 2, 1, 0, 1, 40, 58, }, + { 1, 1, 0, 1, 40, 62, }, + { 3, 1, 0, 1, 40, 62, }, + { 4, 1, 0, 1, 40, 76, }, +- { 5, 1, 0, 1, 40, 62, }, ++ { 5, 1, 0, 1, 40, 58, }, + { 6, 1, 0, 1, 40, 64, }, + { 7, 1, 0, 1, 40, 54, }, + { 8, 1, 0, 1, 40, 62, }, + { 9, 1, 0, 1, 40, 62, }, + { 0, 1, 0, 1, 44, 76, }, +- { 2, 1, 0, 1, 44, 62, }, ++ { 2, 1, 0, 1, 44, 58, }, + { 1, 1, 0, 1, 44, 62, }, + { 3, 1, 0, 1, 44, 62, }, + { 4, 1, 0, 1, 44, 76, }, +- { 5, 1, 0, 1, 44, 62, }, ++ { 5, 1, 0, 1, 44, 58, }, + { 6, 1, 0, 1, 44, 64, }, + { 7, 1, 0, 1, 44, 54, }, + { 8, 1, 0, 1, 44, 62, }, + { 9, 1, 0, 1, 44, 62, }, + { 0, 1, 0, 1, 48, 76, }, +- { 2, 1, 0, 1, 48, 62, }, ++ { 2, 1, 0, 1, 48, 58, }, + { 1, 1, 0, 1, 48, 62, }, + { 3, 1, 0, 1, 48, 62, }, +- { 4, 1, 0, 1, 48, 54, }, +- { 5, 1, 0, 1, 48, 62, }, ++ { 4, 1, 0, 1, 48, 58, }, ++ { 5, 1, 0, 1, 48, 58, }, + { 6, 1, 0, 1, 48, 64, }, + { 7, 1, 0, 1, 48, 54, }, + { 8, 1, 0, 1, 48, 62, }, + { 9, 1, 0, 1, 48, 62, }, + { 0, 1, 0, 1, 52, 76, }, +- { 2, 1, 0, 1, 52, 62, }, ++ { 2, 1, 0, 1, 52, 58, }, + { 1, 1, 0, 1, 52, 62, }, + { 3, 1, 0, 1, 52, 64, }, + { 4, 1, 0, 1, 52, 76, }, +- { 5, 1, 0, 1, 52, 62, }, ++ { 5, 1, 0, 1, 52, 58, }, + { 6, 1, 0, 1, 52, 76, }, + { 7, 1, 0, 1, 52, 54, }, + { 8, 1, 0, 1, 52, 76, }, + { 9, 1, 0, 1, 52, 62, }, + { 0, 1, 0, 1, 56, 76, }, +- { 2, 1, 0, 1, 56, 62, }, ++ { 2, 1, 0, 1, 56, 58, }, + { 1, 1, 0, 1, 56, 62, }, + { 3, 1, 0, 1, 56, 64, }, + { 4, 1, 0, 1, 56, 76, }, +- { 5, 1, 0, 1, 56, 62, }, ++ { 5, 1, 0, 1, 56, 58, }, + { 6, 1, 0, 1, 56, 76, }, + { 7, 1, 0, 1, 56, 54, }, + { 8, 1, 0, 1, 56, 76, }, + { 9, 1, 0, 1, 56, 62, }, + { 0, 1, 0, 1, 60, 76, }, +- { 2, 1, 0, 1, 60, 62, }, ++ { 2, 1, 0, 1, 60, 58, }, + { 1, 1, 0, 1, 60, 62, }, + { 3, 1, 0, 1, 60, 64, }, + { 4, 1, 0, 1, 60, 76, }, +- { 5, 1, 0, 1, 60, 62, }, ++ { 5, 1, 0, 1, 60, 58, }, + { 6, 1, 0, 1, 60, 76, }, + { 7, 1, 0, 1, 60, 54, }, + { 8, 1, 0, 1, 60, 76, }, + { 9, 1, 0, 1, 60, 62, }, +- { 0, 1, 0, 1, 64, 74, }, +- { 2, 1, 0, 1, 64, 62, }, +- { 1, 1, 0, 1, 64, 60, }, ++ { 0, 1, 0, 1, 64, 76, }, ++ { 2, 1, 0, 1, 64, 58, }, ++ { 1, 1, 0, 1, 64, 62, }, + { 3, 1, 0, 1, 64, 64, }, + { 4, 1, 0, 1, 64, 76, }, +- { 5, 1, 0, 1, 64, 62, }, ++ { 5, 1, 0, 1, 64, 58, }, + { 6, 1, 0, 1, 64, 74, }, + { 7, 1, 0, 1, 64, 54, }, + { 8, 1, 0, 1, 64, 74, }, + { 9, 1, 0, 1, 64, 62, }, +- { 0, 1, 0, 1, 100, 72, }, +- { 2, 1, 0, 1, 100, 62, }, ++ { 0, 1, 0, 1, 100, 68, }, ++ { 2, 1, 0, 1, 100, 58, }, + { 1, 1, 0, 1, 100, 76, }, +- { 3, 1, 0, 1, 100, 72, }, ++ { 3, 1, 0, 1, 100, 68, }, + { 4, 1, 0, 1, 100, 76, }, +- { 5, 1, 0, 1, 100, 62, }, ++ { 5, 1, 0, 1, 100, 58, }, + { 6, 1, 0, 1, 100, 72, }, + { 7, 1, 0, 1, 100, 54, }, + { 8, 1, 0, 1, 100, 72, }, + { 9, 1, 0, 1, 100, 127, }, + { 0, 1, 0, 1, 104, 76, }, +- { 2, 1, 0, 1, 104, 62, }, ++ { 2, 1, 0, 1, 104, 58, }, + { 1, 1, 0, 1, 104, 76, }, + { 3, 1, 0, 1, 104, 76, }, + { 4, 1, 0, 1, 104, 76, }, +- { 5, 1, 0, 1, 104, 62, }, ++ { 5, 1, 0, 1, 104, 58, }, + { 6, 1, 0, 1, 104, 76, }, + { 7, 1, 0, 1, 104, 54, }, + { 8, 1, 0, 1, 104, 76, }, + { 9, 1, 0, 1, 104, 127, }, + { 0, 1, 0, 1, 108, 76, }, +- { 2, 1, 0, 1, 108, 62, }, ++ { 2, 1, 0, 1, 108, 58, }, + { 1, 1, 0, 1, 108, 76, }, + { 3, 1, 0, 1, 108, 76, }, + { 4, 1, 0, 1, 108, 76, }, +- { 5, 1, 0, 1, 108, 62, }, ++ { 5, 1, 0, 1, 108, 58, }, + { 6, 1, 0, 1, 108, 76, }, + { 7, 1, 0, 1, 108, 54, }, + { 8, 1, 0, 1, 108, 76, }, + { 9, 1, 0, 1, 108, 127, }, + { 0, 1, 0, 1, 112, 76, }, +- { 2, 1, 0, 1, 112, 62, }, ++ { 2, 1, 0, 1, 112, 58, }, + { 1, 1, 0, 1, 112, 76, }, + { 3, 1, 0, 1, 112, 76, }, + { 4, 1, 0, 1, 112, 76, }, +- { 5, 1, 0, 1, 112, 62, }, ++ { 5, 1, 0, 1, 112, 58, }, + { 6, 1, 0, 1, 112, 76, }, + { 7, 1, 0, 1, 112, 54, }, + { 8, 1, 0, 1, 112, 76, }, + { 9, 1, 0, 1, 112, 127, }, + { 0, 1, 0, 1, 116, 76, }, +- { 2, 1, 0, 1, 116, 62, }, ++ { 2, 1, 0, 1, 116, 58, }, + { 1, 1, 0, 1, 116, 76, }, + { 3, 1, 0, 1, 116, 76, }, + { 4, 1, 0, 1, 116, 76, }, +- { 5, 1, 0, 1, 116, 62, }, ++ { 5, 1, 0, 1, 116, 58, }, + { 6, 1, 0, 1, 116, 76, }, + { 7, 1, 0, 1, 116, 54, }, + { 8, 1, 0, 1, 116, 76, }, + { 9, 1, 0, 1, 116, 127, }, + { 0, 1, 0, 1, 120, 76, }, +- { 2, 1, 0, 1, 120, 62, }, ++ { 2, 1, 0, 1, 120, 58, }, + { 1, 1, 0, 1, 120, 76, }, + { 3, 1, 0, 1, 120, 127, }, + { 4, 1, 0, 1, 120, 76, }, +@@ -26715,7 +42758,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 1, 120, 76, }, + { 9, 1, 0, 1, 120, 127, }, + { 0, 1, 0, 1, 124, 76, }, +- { 2, 1, 0, 1, 124, 62, }, ++ { 2, 1, 0, 1, 124, 58, }, + { 1, 1, 0, 1, 124, 76, }, + { 3, 1, 0, 1, 124, 127, }, + { 4, 1, 0, 1, 124, 76, }, +@@ -26725,7 +42768,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 1, 124, 76, }, + { 9, 1, 0, 1, 124, 127, }, + { 0, 1, 0, 1, 128, 76, }, +- { 2, 1, 0, 1, 128, 62, }, ++ { 2, 1, 0, 1, 128, 58, }, + { 1, 1, 0, 1, 128, 76, }, + { 3, 1, 0, 1, 128, 127, }, + { 4, 1, 0, 1, 128, 76, }, +@@ -26735,38 +42778,38 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 1, 128, 76, }, + { 9, 1, 0, 1, 128, 127, }, + { 0, 1, 0, 1, 132, 76, }, +- { 2, 1, 0, 1, 132, 62, }, ++ { 2, 1, 0, 1, 132, 58, }, + { 1, 1, 0, 1, 132, 76, }, + { 3, 1, 0, 1, 132, 76, }, + { 4, 1, 0, 1, 132, 76, }, +- { 5, 1, 0, 1, 132, 62, }, ++ { 5, 1, 0, 1, 132, 58, }, + { 6, 1, 0, 1, 132, 76, }, + { 7, 1, 0, 1, 132, 54, }, + { 8, 1, 0, 1, 132, 76, }, + { 9, 1, 0, 1, 132, 127, }, + { 0, 1, 0, 1, 136, 76, }, +- { 2, 1, 0, 1, 136, 62, }, ++ { 2, 1, 0, 1, 136, 58, }, + { 1, 1, 0, 1, 136, 76, }, + { 3, 1, 0, 1, 136, 76, }, + { 4, 1, 0, 1, 136, 76, }, +- { 5, 1, 0, 1, 136, 62, }, ++ { 5, 1, 0, 1, 136, 58, }, + { 6, 1, 0, 1, 136, 76, }, + { 7, 1, 0, 1, 136, 54, }, + { 8, 1, 0, 1, 136, 76, }, + { 9, 1, 0, 1, 136, 127, }, +- { 0, 1, 0, 1, 140, 72, }, +- { 2, 1, 0, 1, 140, 62, }, ++ { 0, 1, 0, 1, 140, 74, }, ++ { 2, 1, 0, 1, 140, 58, }, + { 1, 1, 0, 1, 140, 76, }, +- { 3, 1, 0, 1, 140, 72, }, ++ { 3, 1, 0, 1, 140, 74, }, + { 4, 1, 0, 1, 140, 76, }, +- { 5, 1, 0, 1, 140, 62, }, ++ { 5, 1, 0, 1, 140, 58, }, + { 6, 1, 0, 1, 140, 72, }, + { 7, 1, 0, 1, 140, 54, }, + { 8, 1, 0, 1, 140, 72, }, + { 9, 1, 0, 1, 140, 127, }, + { 0, 1, 0, 1, 144, 76, }, + { 2, 1, 0, 1, 144, 127, }, +- { 1, 1, 0, 1, 144, 127, }, ++ { 1, 1, 0, 1, 144, 76, }, + { 3, 1, 0, 1, 144, 76, }, + { 4, 1, 0, 1, 144, 76, }, + { 5, 1, 0, 1, 144, 127, }, +@@ -26775,7 +42818,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 1, 144, 76, }, + { 9, 1, 0, 1, 144, 127, }, + { 0, 1, 0, 1, 149, 76, }, +- { 2, 1, 0, 1, 149, -128, }, ++ { 2, 1, 0, 1, 149, 28, }, + { 1, 1, 0, 1, 149, 127, }, + { 3, 1, 0, 1, 149, 76, }, + { 4, 1, 0, 1, 149, 74, }, +@@ -26783,9 +42826,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 1, 149, 76, }, + { 7, 1, 0, 1, 149, 54, }, + { 8, 1, 0, 1, 149, 76, }, +- { 9, 1, 0, 1, 149, -128, }, ++ { 9, 1, 0, 1, 149, 28, }, + { 0, 1, 0, 1, 153, 76, }, +- { 2, 1, 0, 1, 153, -128, }, ++ { 2, 1, 0, 1, 153, 28, }, + { 1, 1, 0, 1, 153, 127, }, + { 3, 1, 0, 1, 153, 76, }, + { 4, 1, 0, 1, 153, 74, }, +@@ -26793,9 +42836,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 1, 153, 76, }, + { 7, 1, 0, 1, 153, 54, }, + { 8, 1, 0, 1, 153, 76, }, +- { 9, 1, 0, 1, 153, -128, }, ++ { 9, 1, 0, 1, 153, 28, }, + { 0, 1, 0, 1, 157, 76, }, +- { 2, 1, 0, 1, 157, -128, }, ++ { 2, 1, 0, 1, 157, 28, }, + { 1, 1, 0, 1, 157, 127, }, + { 3, 1, 0, 1, 157, 76, }, + { 4, 1, 0, 1, 157, 74, }, +@@ -26803,9 +42846,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 1, 157, 76, }, + { 7, 1, 0, 1, 157, 54, }, + { 8, 1, 0, 1, 157, 76, }, +- { 9, 1, 0, 1, 157, -128, }, ++ { 9, 1, 0, 1, 157, 28, }, + { 0, 1, 0, 1, 161, 76, }, +- { 2, 1, 0, 1, 161, -128, }, ++ { 2, 1, 0, 1, 161, 28, }, + { 1, 1, 0, 1, 161, 127, }, + { 3, 1, 0, 1, 161, 76, }, + { 4, 1, 0, 1, 161, 74, }, +@@ -26813,9 +42856,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 1, 161, 76, }, + { 7, 1, 0, 1, 161, 54, }, + { 8, 1, 0, 1, 161, 76, }, +- { 9, 1, 0, 1, 161, -128, }, ++ { 9, 1, 0, 1, 161, 28, }, + { 0, 1, 0, 1, 165, 76, }, +- { 2, 1, 0, 1, 165, -128, }, ++ { 2, 1, 0, 1, 165, 28, }, + { 1, 1, 0, 1, 165, 127, }, + { 3, 1, 0, 1, 165, 76, }, + { 4, 1, 0, 1, 165, 74, }, +@@ -26823,139 +42866,139 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 1, 165, 76, }, + { 7, 1, 0, 1, 165, 54, }, + { 8, 1, 0, 1, 165, 76, }, +- { 9, 1, 0, 1, 165, -128, }, +- { 0, 1, 0, 2, 36, 72, }, +- { 2, 1, 0, 2, 36, 62, }, +- { 1, 1, 0, 2, 36, 62, }, ++ { 9, 1, 0, 1, 165, 28, }, ++ { 0, 1, 0, 2, 36, 70, }, ++ { 2, 1, 0, 2, 36, 58, }, ++ { 1, 1, 0, 2, 36, 64, }, + { 3, 1, 0, 2, 36, 62, }, + { 4, 1, 0, 2, 36, 76, }, +- { 5, 1, 0, 2, 36, 62, }, ++ { 5, 1, 0, 2, 36, 58, }, + { 6, 1, 0, 2, 36, 64, }, + { 7, 1, 0, 2, 36, 54, }, + { 8, 1, 0, 2, 36, 62, }, + { 9, 1, 0, 2, 36, 62, }, + { 0, 1, 0, 2, 40, 76, }, +- { 2, 1, 0, 2, 40, 62, }, ++ { 2, 1, 0, 2, 40, 58, }, + { 1, 1, 0, 2, 40, 62, }, + { 3, 1, 0, 2, 40, 62, }, + { 4, 1, 0, 2, 40, 76, }, +- { 5, 1, 0, 2, 40, 62, }, ++ { 5, 1, 0, 2, 40, 58, }, + { 6, 1, 0, 2, 40, 64, }, + { 7, 1, 0, 2, 40, 54, }, + { 8, 1, 0, 2, 40, 62, }, + { 9, 1, 0, 2, 40, 62, }, + { 0, 1, 0, 2, 44, 76, }, +- { 2, 1, 0, 2, 44, 62, }, ++ { 2, 1, 0, 2, 44, 58, }, + { 1, 1, 0, 2, 44, 62, }, + { 3, 1, 0, 2, 44, 62, }, + { 4, 1, 0, 2, 44, 76, }, +- { 5, 1, 0, 2, 44, 62, }, ++ { 5, 1, 0, 2, 44, 58, }, + { 6, 1, 0, 2, 44, 64, }, + { 7, 1, 0, 2, 44, 54, }, + { 8, 1, 0, 2, 44, 62, }, + { 9, 1, 0, 2, 44, 62, }, + { 0, 1, 0, 2, 48, 76, }, +- { 2, 1, 0, 2, 48, 62, }, ++ { 2, 1, 0, 2, 48, 58, }, + { 1, 1, 0, 2, 48, 62, }, + { 3, 1, 0, 2, 48, 62, }, +- { 4, 1, 0, 2, 48, 54, }, +- { 5, 1, 0, 2, 48, 62, }, ++ { 4, 1, 0, 2, 48, 58, }, ++ { 5, 1, 0, 2, 48, 58, }, + { 6, 1, 0, 2, 48, 64, }, + { 7, 1, 0, 2, 48, 54, }, + { 8, 1, 0, 2, 48, 62, }, + { 9, 1, 0, 2, 48, 62, }, + { 0, 1, 0, 2, 52, 76, }, +- { 2, 1, 0, 2, 52, 62, }, ++ { 2, 1, 0, 2, 52, 58, }, + { 1, 1, 0, 2, 52, 62, }, + { 3, 1, 0, 2, 52, 64, }, + { 4, 1, 0, 2, 52, 76, }, +- { 5, 1, 0, 2, 52, 62, }, ++ { 5, 1, 0, 2, 52, 58, }, + { 6, 1, 0, 2, 52, 76, }, + { 7, 1, 0, 2, 52, 54, }, + { 8, 1, 0, 2, 52, 76, }, + { 9, 1, 0, 2, 52, 62, }, + { 0, 1, 0, 2, 56, 76, }, +- { 2, 1, 0, 2, 56, 62, }, ++ { 2, 1, 0, 2, 56, 58, }, + { 1, 1, 0, 2, 56, 62, }, + { 3, 1, 0, 2, 56, 64, }, + { 4, 1, 0, 2, 56, 76, }, +- { 5, 1, 0, 2, 56, 62, }, ++ { 5, 1, 0, 2, 56, 58, }, + { 6, 1, 0, 2, 56, 76, }, + { 7, 1, 0, 2, 56, 54, }, + { 8, 1, 0, 2, 56, 76, }, + { 9, 1, 0, 2, 56, 62, }, + { 0, 1, 0, 2, 60, 76, }, +- { 2, 1, 0, 2, 60, 62, }, ++ { 2, 1, 0, 2, 60, 58, }, + { 1, 1, 0, 2, 60, 62, }, + { 3, 1, 0, 2, 60, 64, }, + { 4, 1, 0, 2, 60, 76, }, +- { 5, 1, 0, 2, 60, 62, }, ++ { 5, 1, 0, 2, 60, 58, }, + { 6, 1, 0, 2, 60, 76, }, + { 7, 1, 0, 2, 60, 54, }, + { 8, 1, 0, 2, 60, 76, }, + { 9, 1, 0, 2, 60, 62, }, +- { 0, 1, 0, 2, 64, 74, }, +- { 2, 1, 0, 2, 64, 62, }, +- { 1, 1, 0, 2, 64, 60, }, ++ { 0, 1, 0, 2, 64, 70, }, ++ { 2, 1, 0, 2, 64, 58, }, ++ { 1, 1, 0, 2, 64, 62, }, + { 3, 1, 0, 2, 64, 64, }, + { 4, 1, 0, 2, 64, 74, }, +- { 5, 1, 0, 2, 64, 62, }, ++ { 5, 1, 0, 2, 64, 58, }, + { 6, 1, 0, 2, 64, 74, }, + { 7, 1, 0, 2, 64, 54, }, + { 8, 1, 0, 2, 64, 74, }, + { 9, 1, 0, 2, 64, 62, }, +- { 0, 1, 0, 2, 100, 70, }, +- { 2, 1, 0, 2, 100, 62, }, ++ { 0, 1, 0, 2, 100, 66, }, ++ { 2, 1, 0, 2, 100, 58, }, + { 1, 1, 0, 2, 100, 76, }, +- { 3, 1, 0, 2, 100, 70, }, ++ { 3, 1, 0, 2, 100, 66, }, + { 4, 1, 0, 2, 100, 76, }, +- { 5, 1, 0, 2, 100, 62, }, ++ { 5, 1, 0, 2, 100, 58, }, + { 6, 1, 0, 2, 100, 70, }, + { 7, 1, 0, 2, 100, 54, }, + { 8, 1, 0, 2, 100, 70, }, + { 9, 1, 0, 2, 100, 127, }, + { 0, 1, 0, 2, 104, 76, }, +- { 2, 1, 0, 2, 104, 62, }, ++ { 2, 1, 0, 2, 104, 58, }, + { 1, 1, 0, 2, 104, 76, }, + { 3, 1, 0, 2, 104, 76, }, + { 4, 1, 0, 2, 104, 76, }, +- { 5, 1, 0, 2, 104, 62, }, ++ { 5, 1, 0, 2, 104, 58, }, + { 6, 1, 0, 2, 104, 76, }, + { 7, 1, 0, 2, 104, 54, }, + { 8, 1, 0, 2, 104, 76, }, + { 9, 1, 0, 2, 104, 127, }, + { 0, 1, 0, 2, 108, 76, }, +- { 2, 1, 0, 2, 108, 62, }, ++ { 2, 1, 0, 2, 108, 58, }, + { 1, 1, 0, 2, 108, 76, }, + { 3, 1, 0, 2, 108, 76, }, + { 4, 1, 0, 2, 108, 76, }, +- { 5, 1, 0, 2, 108, 62, }, ++ { 5, 1, 0, 2, 108, 58, }, + { 6, 1, 0, 2, 108, 76, }, + { 7, 1, 0, 2, 108, 54, }, + { 8, 1, 0, 2, 108, 76, }, + { 9, 1, 0, 2, 108, 127, }, + { 0, 1, 0, 2, 112, 76, }, +- { 2, 1, 0, 2, 112, 62, }, ++ { 2, 1, 0, 2, 112, 58, }, + { 1, 1, 0, 2, 112, 76, }, + { 3, 1, 0, 2, 112, 76, }, + { 4, 1, 0, 2, 112, 76, }, +- { 5, 1, 0, 2, 112, 62, }, ++ { 5, 1, 0, 2, 112, 58, }, + { 6, 1, 0, 2, 112, 76, }, + { 7, 1, 0, 2, 112, 54, }, + { 8, 1, 0, 2, 112, 76, }, + { 9, 1, 0, 2, 112, 127, }, + { 0, 1, 0, 2, 116, 76, }, +- { 2, 1, 0, 2, 116, 62, }, ++ { 2, 1, 0, 2, 116, 58, }, + { 1, 1, 0, 2, 116, 76, }, + { 3, 1, 0, 2, 116, 76, }, + { 4, 1, 0, 2, 116, 76, }, +- { 5, 1, 0, 2, 116, 62, }, ++ { 5, 1, 0, 2, 116, 58, }, + { 6, 1, 0, 2, 116, 76, }, + { 7, 1, 0, 2, 116, 54, }, + { 8, 1, 0, 2, 116, 76, }, + { 9, 1, 0, 2, 116, 127, }, + { 0, 1, 0, 2, 120, 76, }, +- { 2, 1, 0, 2, 120, 62, }, ++ { 2, 1, 0, 2, 120, 58, }, + { 1, 1, 0, 2, 120, 76, }, + { 3, 1, 0, 2, 120, 127, }, + { 4, 1, 0, 2, 120, 76, }, +@@ -26965,7 +43008,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 2, 120, 76, }, + { 9, 1, 0, 2, 120, 127, }, + { 0, 1, 0, 2, 124, 76, }, +- { 2, 1, 0, 2, 124, 62, }, ++ { 2, 1, 0, 2, 124, 58, }, + { 1, 1, 0, 2, 124, 76, }, + { 3, 1, 0, 2, 124, 127, }, + { 4, 1, 0, 2, 124, 76, }, +@@ -26975,7 +43018,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 2, 124, 76, }, + { 9, 1, 0, 2, 124, 127, }, + { 0, 1, 0, 2, 128, 76, }, +- { 2, 1, 0, 2, 128, 62, }, ++ { 2, 1, 0, 2, 128, 58, }, + { 1, 1, 0, 2, 128, 76, }, + { 3, 1, 0, 2, 128, 127, }, + { 4, 1, 0, 2, 128, 76, }, +@@ -26985,38 +43028,38 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 2, 128, 76, }, + { 9, 1, 0, 2, 128, 127, }, + { 0, 1, 0, 2, 132, 76, }, +- { 2, 1, 0, 2, 132, 62, }, ++ { 2, 1, 0, 2, 132, 58, }, + { 1, 1, 0, 2, 132, 76, }, + { 3, 1, 0, 2, 132, 76, }, + { 4, 1, 0, 2, 132, 76, }, +- { 5, 1, 0, 2, 132, 62, }, ++ { 5, 1, 0, 2, 132, 58, }, + { 6, 1, 0, 2, 132, 76, }, + { 7, 1, 0, 2, 132, 54, }, + { 8, 1, 0, 2, 132, 76, }, + { 9, 1, 0, 2, 132, 127, }, + { 0, 1, 0, 2, 136, 76, }, +- { 2, 1, 0, 2, 136, 62, }, ++ { 2, 1, 0, 2, 136, 58, }, + { 1, 1, 0, 2, 136, 76, }, + { 3, 1, 0, 2, 136, 76, }, + { 4, 1, 0, 2, 136, 76, }, +- { 5, 1, 0, 2, 136, 62, }, ++ { 5, 1, 0, 2, 136, 58, }, + { 6, 1, 0, 2, 136, 76, }, + { 7, 1, 0, 2, 136, 54, }, + { 8, 1, 0, 2, 136, 76, }, + { 9, 1, 0, 2, 136, 127, }, +- { 0, 1, 0, 2, 140, 70, }, +- { 2, 1, 0, 2, 140, 62, }, ++ { 0, 1, 0, 2, 140, 66, }, ++ { 2, 1, 0, 2, 140, 58, }, + { 1, 1, 0, 2, 140, 76, }, +- { 3, 1, 0, 2, 140, 70, }, ++ { 3, 1, 0, 2, 140, 66, }, + { 4, 1, 0, 2, 140, 76, }, +- { 5, 1, 0, 2, 140, 62, }, ++ { 5, 1, 0, 2, 140, 58, }, + { 6, 1, 0, 2, 140, 70, }, + { 7, 1, 0, 2, 140, 54, }, + { 8, 1, 0, 2, 140, 70, }, + { 9, 1, 0, 2, 140, 127, }, + { 0, 1, 0, 2, 144, 76, }, + { 2, 1, 0, 2, 144, 127, }, +- { 1, 1, 0, 2, 144, 127, }, ++ { 1, 1, 0, 2, 144, 76, }, + { 3, 1, 0, 2, 144, 76, }, + { 4, 1, 0, 2, 144, 76, }, + { 5, 1, 0, 2, 144, 127, }, +@@ -27025,7 +43068,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 0, 2, 144, 76, }, + { 9, 1, 0, 2, 144, 127, }, + { 0, 1, 0, 2, 149, 76, }, +- { 2, 1, 0, 2, 149, -128, }, ++ { 2, 1, 0, 2, 149, 28, }, + { 1, 1, 0, 2, 149, 127, }, + { 3, 1, 0, 2, 149, 76, }, + { 4, 1, 0, 2, 149, 74, }, +@@ -27033,9 +43076,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 2, 149, 76, }, + { 7, 1, 0, 2, 149, 54, }, + { 8, 1, 0, 2, 149, 76, }, +- { 9, 1, 0, 2, 149, -128, }, ++ { 9, 1, 0, 2, 149, 28, }, + { 0, 1, 0, 2, 153, 76, }, +- { 2, 1, 0, 2, 153, -128, }, ++ { 2, 1, 0, 2, 153, 28, }, + { 1, 1, 0, 2, 153, 127, }, + { 3, 1, 0, 2, 153, 76, }, + { 4, 1, 0, 2, 153, 74, }, +@@ -27043,9 +43086,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 2, 153, 76, }, + { 7, 1, 0, 2, 153, 54, }, + { 8, 1, 0, 2, 153, 76, }, +- { 9, 1, 0, 2, 153, -128, }, ++ { 9, 1, 0, 2, 153, 28, }, + { 0, 1, 0, 2, 157, 76, }, +- { 2, 1, 0, 2, 157, -128, }, ++ { 2, 1, 0, 2, 157, 28, }, + { 1, 1, 0, 2, 157, 127, }, + { 3, 1, 0, 2, 157, 76, }, + { 4, 1, 0, 2, 157, 74, }, +@@ -27053,9 +43096,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 2, 157, 76, }, + { 7, 1, 0, 2, 157, 54, }, + { 8, 1, 0, 2, 157, 76, }, +- { 9, 1, 0, 2, 157, -128, }, ++ { 9, 1, 0, 2, 157, 28, }, + { 0, 1, 0, 2, 161, 76, }, +- { 2, 1, 0, 2, 161, -128, }, ++ { 2, 1, 0, 2, 161, 28, }, + { 1, 1, 0, 2, 161, 127, }, + { 3, 1, 0, 2, 161, 76, }, + { 4, 1, 0, 2, 161, 74, }, +@@ -27063,9 +43106,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 2, 161, 76, }, + { 7, 1, 0, 2, 161, 54, }, + { 8, 1, 0, 2, 161, 76, }, +- { 9, 1, 0, 2, 161, -128, }, ++ { 9, 1, 0, 2, 161, 28, }, + { 0, 1, 0, 2, 165, 76, }, +- { 2, 1, 0, 2, 165, -128, }, ++ { 2, 1, 0, 2, 165, 28, }, + { 1, 1, 0, 2, 165, 127, }, + { 3, 1, 0, 2, 165, 76, }, + { 4, 1, 0, 2, 165, 74, }, +@@ -27073,262 +43116,262 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 0, 2, 165, 76, }, + { 7, 1, 0, 2, 165, 54, }, + { 8, 1, 0, 2, 165, 76, }, +- { 9, 1, 0, 2, 165, -128, }, +- { 0, 1, 0, 3, 36, 68, }, +- { 2, 1, 0, 3, 36, 38, }, ++ { 9, 1, 0, 2, 165, 28, }, ++ { 0, 1, 0, 3, 36, 64, }, ++ { 2, 1, 0, 3, 36, 36, }, + { 1, 1, 0, 3, 36, 50, }, + { 3, 1, 0, 3, 36, 38, }, + { 4, 1, 0, 3, 36, 66, }, +- { 5, 1, 0, 3, 36, 38, }, ++ { 5, 1, 0, 3, 36, 36, }, + { 6, 1, 0, 3, 36, 52, }, + { 7, 1, 0, 3, 36, 30, }, + { 8, 1, 0, 3, 36, 50, }, + { 9, 1, 0, 3, 36, 38, }, + { 0, 1, 0, 3, 40, 68, }, +- { 2, 1, 0, 3, 40, 38, }, ++ { 2, 1, 0, 3, 40, 36, }, + { 1, 1, 0, 3, 40, 50, }, + { 3, 1, 0, 3, 40, 38, }, + { 4, 1, 0, 3, 40, 66, }, +- { 5, 1, 0, 3, 40, 38, }, ++ { 5, 1, 0, 3, 40, 36, }, + { 6, 1, 0, 3, 40, 52, }, + { 7, 1, 0, 3, 40, 30, }, + { 8, 1, 0, 3, 40, 50, }, + { 9, 1, 0, 3, 40, 38, }, + { 0, 1, 0, 3, 44, 68, }, +- { 2, 1, 0, 3, 44, 38, }, ++ { 2, 1, 0, 3, 44, 36, }, + { 1, 1, 0, 3, 44, 50, }, + { 3, 1, 0, 3, 44, 38, }, + { 4, 1, 0, 3, 44, 66, }, +- { 5, 1, 0, 3, 44, 38, }, ++ { 5, 1, 0, 3, 44, 36, }, + { 6, 1, 0, 3, 44, 52, }, + { 7, 1, 0, 3, 44, 30, }, + { 8, 1, 0, 3, 44, 50, }, + { 9, 1, 0, 3, 44, 38, }, + { 0, 1, 0, 3, 48, 68, }, +- { 2, 1, 0, 3, 48, 38, }, ++ { 2, 1, 0, 3, 48, 36, }, + { 1, 1, 0, 3, 48, 50, }, + { 3, 1, 0, 3, 48, 38, }, +- { 4, 1, 0, 3, 48, 36, }, +- { 5, 1, 0, 3, 48, 38, }, ++ { 4, 1, 0, 3, 48, 42, }, ++ { 5, 1, 0, 3, 48, 36, }, + { 6, 1, 0, 3, 48, 52, }, + { 7, 1, 0, 3, 48, 30, }, + { 8, 1, 0, 3, 48, 50, }, + { 9, 1, 0, 3, 48, 38, }, + { 0, 1, 0, 3, 52, 68, }, +- { 2, 1, 0, 3, 52, 38, }, ++ { 2, 1, 0, 3, 52, 36, }, + { 1, 1, 0, 3, 52, 50, }, + { 3, 1, 0, 3, 52, 40, }, + { 4, 1, 0, 3, 52, 66, }, +- { 5, 1, 0, 3, 52, 38, }, ++ { 5, 1, 0, 3, 52, 36, }, + { 6, 1, 0, 3, 52, 68, }, + { 7, 1, 0, 3, 52, 30, }, + { 8, 1, 0, 3, 52, 68, }, + { 9, 1, 0, 3, 52, 38, }, + { 0, 1, 0, 3, 56, 68, }, +- { 2, 1, 0, 3, 56, 38, }, ++ { 2, 1, 0, 3, 56, 36, }, + { 1, 1, 0, 3, 56, 50, }, + { 3, 1, 0, 3, 56, 40, }, + { 4, 1, 0, 3, 56, 66, }, +- { 5, 1, 0, 3, 56, 38, }, ++ { 5, 1, 0, 3, 56, 36, }, + { 6, 1, 0, 3, 56, 68, }, + { 7, 1, 0, 3, 56, 30, }, + { 8, 1, 0, 3, 56, 68, }, + { 9, 1, 0, 3, 56, 38, }, +- { 0, 1, 0, 3, 60, 66, }, +- { 2, 1, 0, 3, 60, 38, }, ++ { 0, 1, 0, 3, 60, 68, }, ++ { 2, 1, 0, 3, 60, 36, }, + { 1, 1, 0, 3, 60, 50, }, + { 3, 1, 0, 3, 60, 40, }, + { 4, 1, 0, 3, 60, 66, }, +- { 5, 1, 0, 3, 60, 38, }, ++ { 5, 1, 0, 3, 60, 36, }, + { 6, 1, 0, 3, 60, 66, }, + { 7, 1, 0, 3, 60, 30, }, + { 8, 1, 0, 3, 60, 66, }, + { 9, 1, 0, 3, 60, 38, }, +- { 0, 1, 0, 3, 64, 68, }, +- { 2, 1, 0, 3, 64, 38, }, ++ { 0, 1, 0, 3, 64, 66, }, ++ { 2, 1, 0, 3, 64, 36, }, + { 1, 1, 0, 3, 64, 50, }, + { 3, 1, 0, 3, 64, 40, }, + { 4, 1, 0, 3, 64, 66, }, +- { 5, 1, 0, 3, 64, 38, }, ++ { 5, 1, 0, 3, 64, 36, }, + { 6, 1, 0, 3, 64, 68, }, + { 7, 1, 0, 3, 64, 30, }, + { 8, 1, 0, 3, 64, 68, }, + { 9, 1, 0, 3, 64, 38, }, +- { 0, 1, 0, 3, 100, 60, }, +- { 2, 1, 0, 3, 100, 38, }, ++ { 0, 1, 0, 3, 100, 64, }, ++ { 2, 1, 0, 3, 100, 36, }, + { 1, 1, 0, 3, 100, 70, }, +- { 3, 1, 0, 3, 100, 60, }, +- { 4, 1, 0, 3, 100, 64, }, +- { 5, 1, 0, 3, 100, 38, }, ++ { 3, 1, 0, 3, 100, 64, }, ++ { 4, 1, 0, 3, 100, 66, }, ++ { 5, 1, 0, 3, 100, 36, }, + { 6, 1, 0, 3, 100, 60, }, + { 7, 1, 0, 3, 100, 30, }, + { 8, 1, 0, 3, 100, 60, }, + { 9, 1, 0, 3, 100, 127, }, + { 0, 1, 0, 3, 104, 68, }, +- { 2, 1, 0, 3, 104, 38, }, ++ { 2, 1, 0, 3, 104, 36, }, + { 1, 1, 0, 3, 104, 70, }, + { 3, 1, 0, 3, 104, 68, }, +- { 4, 1, 0, 3, 104, 64, }, +- { 5, 1, 0, 3, 104, 38, }, ++ { 4, 1, 0, 3, 104, 66, }, ++ { 5, 1, 0, 3, 104, 36, }, + { 6, 1, 0, 3, 104, 68, }, + { 7, 1, 0, 3, 104, 30, }, + { 8, 1, 0, 3, 104, 68, }, + { 9, 1, 0, 3, 104, 127, }, + { 0, 1, 0, 3, 108, 68, }, +- { 2, 1, 0, 3, 108, 38, }, ++ { 2, 1, 0, 3, 108, 36, }, + { 1, 1, 0, 3, 108, 70, }, + { 3, 1, 0, 3, 108, 68, }, +- { 4, 1, 0, 3, 108, 64, }, +- { 5, 1, 0, 3, 108, 38, }, ++ { 4, 1, 0, 3, 108, 66, }, ++ { 5, 1, 0, 3, 108, 36, }, + { 6, 1, 0, 3, 108, 68, }, + { 7, 1, 0, 3, 108, 30, }, + { 8, 1, 0, 3, 108, 68, }, + { 9, 1, 0, 3, 108, 127, }, + { 0, 1, 0, 3, 112, 68, }, +- { 2, 1, 0, 3, 112, 38, }, ++ { 2, 1, 0, 3, 112, 36, }, + { 1, 1, 0, 3, 112, 70, }, + { 3, 1, 0, 3, 112, 68, }, +- { 4, 1, 0, 3, 112, 64, }, +- { 5, 1, 0, 3, 112, 38, }, ++ { 4, 1, 0, 3, 112, 66, }, ++ { 5, 1, 0, 3, 112, 36, }, + { 6, 1, 0, 3, 112, 68, }, + { 7, 1, 0, 3, 112, 30, }, + { 8, 1, 0, 3, 112, 68, }, + { 9, 1, 0, 3, 112, 127, }, + { 0, 1, 0, 3, 116, 68, }, +- { 2, 1, 0, 3, 116, 38, }, ++ { 2, 1, 0, 3, 116, 36, }, + { 1, 1, 0, 3, 116, 70, }, + { 3, 1, 0, 3, 116, 68, }, +- { 4, 1, 0, 3, 116, 64, }, +- { 5, 1, 0, 3, 116, 38, }, ++ { 4, 1, 0, 3, 116, 66, }, ++ { 5, 1, 0, 3, 116, 36, }, + { 6, 1, 0, 3, 116, 68, }, + { 7, 1, 0, 3, 116, 30, }, + { 8, 1, 0, 3, 116, 68, }, + { 9, 1, 0, 3, 116, 127, }, + { 0, 1, 0, 3, 120, 68, }, +- { 2, 1, 0, 3, 120, 38, }, ++ { 2, 1, 0, 3, 120, 36, }, + { 1, 1, 0, 3, 120, 70, }, + { 3, 1, 0, 3, 120, 127, }, +- { 4, 1, 0, 3, 120, 64, }, ++ { 4, 1, 0, 3, 120, 66, }, + { 5, 1, 0, 3, 120, 127, }, + { 6, 1, 0, 3, 120, 68, }, + { 7, 1, 0, 3, 120, 30, }, + { 8, 1, 0, 3, 120, 68, }, + { 9, 1, 0, 3, 120, 127, }, + { 0, 1, 0, 3, 124, 68, }, +- { 2, 1, 0, 3, 124, 38, }, ++ { 2, 1, 0, 3, 124, 36, }, + { 1, 1, 0, 3, 124, 70, }, + { 3, 1, 0, 3, 124, 127, }, +- { 4, 1, 0, 3, 124, 64, }, ++ { 4, 1, 0, 3, 124, 66, }, + { 5, 1, 0, 3, 124, 127, }, + { 6, 1, 0, 3, 124, 68, }, + { 7, 1, 0, 3, 124, 30, }, + { 8, 1, 0, 3, 124, 68, }, + { 9, 1, 0, 3, 124, 127, }, + { 0, 1, 0, 3, 128, 68, }, +- { 2, 1, 0, 3, 128, 38, }, ++ { 2, 1, 0, 3, 128, 36, }, + { 1, 1, 0, 3, 128, 70, }, + { 3, 1, 0, 3, 128, 127, }, +- { 4, 1, 0, 3, 128, 64, }, ++ { 4, 1, 0, 3, 128, 66, }, + { 5, 1, 0, 3, 128, 127, }, + { 6, 1, 0, 3, 128, 68, }, + { 7, 1, 0, 3, 128, 30, }, + { 8, 1, 0, 3, 128, 68, }, + { 9, 1, 0, 3, 128, 127, }, + { 0, 1, 0, 3, 132, 68, }, +- { 2, 1, 0, 3, 132, 38, }, ++ { 2, 1, 0, 3, 132, 36, }, + { 1, 1, 0, 3, 132, 70, }, + { 3, 1, 0, 3, 132, 68, }, +- { 4, 1, 0, 3, 132, 64, }, +- { 5, 1, 0, 3, 132, 38, }, ++ { 4, 1, 0, 3, 132, 66, }, ++ { 5, 1, 0, 3, 132, 36, }, + { 6, 1, 0, 3, 132, 68, }, + { 7, 1, 0, 3, 132, 30, }, + { 8, 1, 0, 3, 132, 68, }, + { 9, 1, 0, 3, 132, 127, }, + { 0, 1, 0, 3, 136, 68, }, +- { 2, 1, 0, 3, 136, 38, }, ++ { 2, 1, 0, 3, 136, 36, }, + { 1, 1, 0, 3, 136, 70, }, + { 3, 1, 0, 3, 136, 68, }, +- { 4, 1, 0, 3, 136, 64, }, +- { 5, 1, 0, 3, 136, 38, }, ++ { 4, 1, 0, 3, 136, 66, }, ++ { 5, 1, 0, 3, 136, 36, }, + { 6, 1, 0, 3, 136, 68, }, + { 7, 1, 0, 3, 136, 30, }, + { 8, 1, 0, 3, 136, 68, }, + { 9, 1, 0, 3, 136, 127, }, +- { 0, 1, 0, 3, 140, 60, }, +- { 2, 1, 0, 3, 140, 38, }, ++ { 0, 1, 0, 3, 140, 58, }, ++ { 2, 1, 0, 3, 140, 36, }, + { 1, 1, 0, 3, 140, 70, }, +- { 3, 1, 0, 3, 140, 60, }, +- { 4, 1, 0, 3, 140, 64, }, +- { 5, 1, 0, 3, 140, 38, }, ++ { 3, 1, 0, 3, 140, 58, }, ++ { 4, 1, 0, 3, 140, 66, }, ++ { 5, 1, 0, 3, 140, 36, }, + { 6, 1, 0, 3, 140, 60, }, + { 7, 1, 0, 3, 140, 30, }, + { 8, 1, 0, 3, 140, 60, }, + { 9, 1, 0, 3, 140, 127, }, + { 0, 1, 0, 3, 144, 68, }, + { 2, 1, 0, 3, 144, 127, }, +- { 1, 1, 0, 3, 144, 127, }, ++ { 1, 1, 0, 3, 144, 70, }, + { 3, 1, 0, 3, 144, 68, }, +- { 4, 1, 0, 3, 144, 64, }, ++ { 4, 1, 0, 3, 144, 66, }, + { 5, 1, 0, 3, 144, 127, }, + { 6, 1, 0, 3, 144, 68, }, + { 7, 1, 0, 3, 144, 127, }, + { 8, 1, 0, 3, 144, 68, }, + { 9, 1, 0, 3, 144, 127, }, + { 0, 1, 0, 3, 149, 76, }, +- { 2, 1, 0, 3, 149, -128, }, ++ { 2, 1, 0, 3, 149, 4, }, + { 1, 1, 0, 3, 149, 127, }, + { 3, 1, 0, 3, 149, 76, }, +- { 4, 1, 0, 3, 149, 60, }, ++ { 4, 1, 0, 3, 149, 62, }, + { 5, 1, 0, 3, 149, 76, }, + { 6, 1, 0, 3, 149, 76, }, + { 7, 1, 0, 3, 149, 30, }, + { 8, 1, 0, 3, 149, 72, }, +- { 9, 1, 0, 3, 149, -128, }, ++ { 9, 1, 0, 3, 149, 4, }, + { 0, 1, 0, 3, 153, 76, }, +- { 2, 1, 0, 3, 153, -128, }, ++ { 2, 1, 0, 3, 153, 4, }, + { 1, 1, 0, 3, 153, 127, }, + { 3, 1, 0, 3, 153, 76, }, +- { 4, 1, 0, 3, 153, 60, }, ++ { 4, 1, 0, 3, 153, 62, }, + { 5, 1, 0, 3, 153, 76, }, + { 6, 1, 0, 3, 153, 76, }, + { 7, 1, 0, 3, 153, 30, }, + { 8, 1, 0, 3, 153, 76, }, +- { 9, 1, 0, 3, 153, -128, }, ++ { 9, 1, 0, 3, 153, 4, }, + { 0, 1, 0, 3, 157, 76, }, +- { 2, 1, 0, 3, 157, -128, }, ++ { 2, 1, 0, 3, 157, 4, }, + { 1, 1, 0, 3, 157, 127, }, + { 3, 1, 0, 3, 157, 76, }, +- { 4, 1, 0, 3, 157, 60, }, ++ { 4, 1, 0, 3, 157, 62, }, + { 5, 1, 0, 3, 157, 76, }, + { 6, 1, 0, 3, 157, 76, }, + { 7, 1, 0, 3, 157, 30, }, + { 8, 1, 0, 3, 157, 76, }, +- { 9, 1, 0, 3, 157, -128, }, ++ { 9, 1, 0, 3, 157, 4, }, + { 0, 1, 0, 3, 161, 76, }, +- { 2, 1, 0, 3, 161, -128, }, ++ { 2, 1, 0, 3, 161, 4, }, + { 1, 1, 0, 3, 161, 127, }, + { 3, 1, 0, 3, 161, 76, }, +- { 4, 1, 0, 3, 161, 60, }, ++ { 4, 1, 0, 3, 161, 62, }, + { 5, 1, 0, 3, 161, 76, }, + { 6, 1, 0, 3, 161, 76, }, + { 7, 1, 0, 3, 161, 30, }, + { 8, 1, 0, 3, 161, 76, }, +- { 9, 1, 0, 3, 161, -128, }, ++ { 9, 1, 0, 3, 161, 4, }, + { 0, 1, 0, 3, 165, 76, }, +- { 2, 1, 0, 3, 165, -128, }, ++ { 2, 1, 0, 3, 165, 4, }, + { 1, 1, 0, 3, 165, 127, }, + { 3, 1, 0, 3, 165, 76, }, +- { 4, 1, 0, 3, 165, 60, }, ++ { 4, 1, 0, 3, 165, 62, }, + { 5, 1, 0, 3, 165, 76, }, + { 6, 1, 0, 3, 165, 76, }, + { 7, 1, 0, 3, 165, 30, }, + { 8, 1, 0, 3, 165, 76, }, +- { 9, 1, 0, 3, 165, -128, }, ++ { 9, 1, 0, 3, 165, 4, }, + { 0, 1, 1, 2, 38, 66, }, + { 2, 1, 1, 2, 38, 64, }, +- { 1, 1, 1, 2, 38, 62, }, ++ { 1, 1, 1, 2, 38, 64, }, + { 3, 1, 1, 2, 38, 64, }, +- { 4, 1, 1, 2, 38, 72, }, ++ { 4, 1, 1, 2, 38, 64, }, + { 5, 1, 1, 2, 38, 64, }, + { 6, 1, 1, 2, 38, 64, }, + { 7, 1, 1, 2, 38, 54, }, +@@ -27336,9 +43379,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 9, 1, 1, 2, 38, 64, }, + { 0, 1, 1, 2, 46, 72, }, + { 2, 1, 1, 2, 46, 64, }, +- { 1, 1, 1, 2, 46, 62, }, ++ { 1, 1, 1, 2, 46, 64, }, + { 3, 1, 1, 2, 46, 64, }, +- { 4, 1, 1, 2, 46, 60, }, ++ { 4, 1, 1, 2, 46, 70, }, + { 5, 1, 1, 2, 46, 64, }, + { 6, 1, 1, 2, 46, 64, }, + { 7, 1, 1, 2, 46, 54, }, +@@ -27346,7 +43389,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 9, 1, 1, 2, 46, 64, }, + { 0, 1, 1, 2, 54, 72, }, + { 2, 1, 1, 2, 54, 64, }, +- { 1, 1, 1, 2, 54, 62, }, ++ { 1, 1, 1, 2, 54, 64, }, + { 3, 1, 1, 2, 54, 64, }, + { 4, 1, 1, 2, 54, 72, }, + { 5, 1, 1, 2, 54, 64, }, +@@ -27354,21 +43397,21 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 7, 1, 1, 2, 54, 54, }, + { 8, 1, 1, 2, 54, 72, }, + { 9, 1, 1, 2, 54, 64, }, +- { 0, 1, 1, 2, 62, 64, }, ++ { 0, 1, 1, 2, 62, 60, }, + { 2, 1, 1, 2, 62, 64, }, + { 1, 1, 1, 2, 62, 62, }, +- { 3, 1, 1, 2, 62, 64, }, +- { 4, 1, 1, 2, 62, 70, }, ++ { 3, 1, 1, 2, 62, 60, }, ++ { 4, 1, 1, 2, 62, 60, }, + { 5, 1, 1, 2, 62, 64, }, + { 6, 1, 1, 2, 62, 64, }, + { 7, 1, 1, 2, 62, 54, }, + { 8, 1, 1, 2, 62, 64, }, + { 9, 1, 1, 2, 62, 64, }, +- { 0, 1, 1, 2, 102, 58, }, ++ { 0, 1, 1, 2, 102, 60, }, + { 2, 1, 1, 2, 102, 64, }, + { 1, 1, 1, 2, 102, 72, }, +- { 3, 1, 1, 2, 102, 58, }, +- { 4, 1, 1, 2, 102, 72, }, ++ { 3, 1, 1, 2, 102, 60, }, ++ { 4, 1, 1, 2, 102, 64, }, + { 5, 1, 1, 2, 102, 64, }, + { 6, 1, 1, 2, 102, 58, }, + { 7, 1, 1, 2, 102, 54, }, +@@ -27416,7 +43459,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 9, 1, 1, 2, 134, 127, }, + { 0, 1, 1, 2, 142, 72, }, + { 2, 1, 1, 2, 142, 127, }, +- { 1, 1, 1, 2, 142, 127, }, ++ { 1, 1, 1, 2, 142, 72, }, + { 3, 1, 1, 2, 142, 72, }, + { 4, 1, 1, 2, 142, 72, }, + { 5, 1, 1, 2, 142, 127, }, +@@ -27425,7 +43468,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 8, 1, 1, 2, 142, 72, }, + { 9, 1, 1, 2, 142, 127, }, + { 0, 1, 1, 2, 151, 72, }, +- { 2, 1, 1, 2, 151, -128, }, ++ { 2, 1, 1, 2, 151, 28, }, + { 1, 1, 1, 2, 151, 127, }, + { 3, 1, 1, 2, 151, 72, }, + { 4, 1, 1, 2, 151, 72, }, +@@ -27433,9 +43476,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 1, 2, 151, 72, }, + { 7, 1, 1, 2, 151, 54, }, + { 8, 1, 1, 2, 151, 72, }, +- { 9, 1, 1, 2, 151, -128, }, ++ { 9, 1, 1, 2, 151, 28, }, + { 0, 1, 1, 2, 159, 72, }, +- { 2, 1, 1, 2, 159, -128, }, ++ { 2, 1, 1, 2, 159, 28, }, + { 1, 1, 1, 2, 159, 127, }, + { 3, 1, 1, 2, 159, 72, }, + { 4, 1, 1, 2, 159, 72, }, +@@ -27443,12 +43486,12 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 1, 2, 159, 72, }, + { 7, 1, 1, 2, 159, 54, }, + { 8, 1, 1, 2, 159, 72, }, +- { 9, 1, 1, 2, 159, -128, }, ++ { 9, 1, 1, 2, 159, 28, }, + { 0, 1, 1, 3, 38, 60, }, + { 2, 1, 1, 3, 38, 40, }, + { 1, 1, 1, 3, 38, 50, }, + { 3, 1, 1, 3, 38, 40, }, +- { 4, 1, 1, 3, 38, 62, }, ++ { 4, 1, 1, 3, 38, 54, }, + { 5, 1, 1, 3, 38, 40, }, + { 6, 1, 1, 3, 38, 52, }, + { 7, 1, 1, 3, 38, 30, }, +@@ -27458,7 +43501,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 46, 40, }, + { 1, 1, 1, 3, 46, 50, }, + { 3, 1, 1, 3, 46, 40, }, +- { 4, 1, 1, 3, 46, 46, }, ++ { 4, 1, 1, 3, 46, 54, }, + { 5, 1, 1, 3, 46, 40, }, + { 6, 1, 1, 3, 46, 52, }, + { 7, 1, 1, 3, 46, 30, }, +@@ -27468,7 +43511,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 54, 40, }, + { 1, 1, 1, 3, 54, 50, }, + { 3, 1, 1, 3, 54, 40, }, +- { 4, 1, 1, 3, 54, 62, }, ++ { 4, 1, 1, 3, 54, 66, }, + { 5, 1, 1, 3, 54, 40, }, + { 6, 1, 1, 3, 54, 68, }, + { 7, 1, 1, 3, 54, 30, }, +@@ -27478,17 +43521,17 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 62, 40, }, + { 1, 1, 1, 3, 62, 48, }, + { 3, 1, 1, 3, 62, 40, }, +- { 4, 1, 1, 3, 62, 58, }, ++ { 4, 1, 1, 3, 62, 50, }, + { 5, 1, 1, 3, 62, 40, }, + { 6, 1, 1, 3, 62, 58, }, + { 7, 1, 1, 3, 62, 30, }, + { 8, 1, 1, 3, 62, 58, }, + { 9, 1, 1, 3, 62, 40, }, +- { 0, 1, 1, 3, 102, 54, }, ++ { 0, 1, 1, 3, 102, 56, }, + { 2, 1, 1, 3, 102, 40, }, + { 1, 1, 1, 3, 102, 70, }, +- { 3, 1, 1, 3, 102, 54, }, +- { 4, 1, 1, 3, 102, 64, }, ++ { 3, 1, 1, 3, 102, 56, }, ++ { 4, 1, 1, 3, 102, 54, }, + { 5, 1, 1, 3, 102, 40, }, + { 6, 1, 1, 3, 102, 54, }, + { 7, 1, 1, 3, 102, 30, }, +@@ -27498,7 +43541,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 110, 40, }, + { 1, 1, 1, 3, 110, 70, }, + { 3, 1, 1, 3, 110, 68, }, +- { 4, 1, 1, 3, 110, 64, }, ++ { 4, 1, 1, 3, 110, 66, }, + { 5, 1, 1, 3, 110, 40, }, + { 6, 1, 1, 3, 110, 68, }, + { 7, 1, 1, 3, 110, 30, }, +@@ -27508,7 +43551,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 118, 40, }, + { 1, 1, 1, 3, 118, 70, }, + { 3, 1, 1, 3, 118, 127, }, +- { 4, 1, 1, 3, 118, 64, }, ++ { 4, 1, 1, 3, 118, 66, }, + { 5, 1, 1, 3, 118, 127, }, + { 6, 1, 1, 3, 118, 68, }, + { 7, 1, 1, 3, 118, 30, }, +@@ -27518,7 +43561,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 126, 40, }, + { 1, 1, 1, 3, 126, 70, }, + { 3, 1, 1, 3, 126, 127, }, +- { 4, 1, 1, 3, 126, 64, }, ++ { 4, 1, 1, 3, 126, 66, }, + { 5, 1, 1, 3, 126, 127, }, + { 6, 1, 1, 3, 126, 68, }, + { 7, 1, 1, 3, 126, 30, }, +@@ -27528,7 +43571,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 2, 1, 1, 3, 134, 40, }, + { 1, 1, 1, 3, 134, 70, }, + { 3, 1, 1, 3, 134, 68, }, +- { 4, 1, 1, 3, 134, 64, }, ++ { 4, 1, 1, 3, 134, 66, }, + { 5, 1, 1, 3, 134, 40, }, + { 6, 1, 1, 3, 134, 68, }, + { 7, 1, 1, 3, 134, 30, }, +@@ -27536,16 +43579,16 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 9, 1, 1, 3, 134, 127, }, + { 0, 1, 1, 3, 142, 68, }, + { 2, 1, 1, 3, 142, 127, }, +- { 1, 1, 1, 3, 142, 127, }, ++ { 1, 1, 1, 3, 142, 70, }, + { 3, 1, 1, 3, 142, 68, }, +- { 4, 1, 1, 3, 142, 64, }, ++ { 4, 1, 1, 3, 142, 66, }, + { 5, 1, 1, 3, 142, 127, }, + { 6, 1, 1, 3, 142, 68, }, + { 7, 1, 1, 3, 142, 127, }, + { 8, 1, 1, 3, 142, 68, }, + { 9, 1, 1, 3, 142, 127, }, + { 0, 1, 1, 3, 151, 72, }, +- { 2, 1, 1, 3, 151, -128, }, ++ { 2, 1, 1, 3, 151, 4, }, + { 1, 1, 1, 3, 151, 127, }, + { 3, 1, 1, 3, 151, 72, }, + { 4, 1, 1, 3, 151, 66, }, +@@ -27553,9 +43596,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 1, 3, 151, 72, }, + { 7, 1, 1, 3, 151, 30, }, + { 8, 1, 1, 3, 151, 68, }, +- { 9, 1, 1, 3, 151, -128, }, ++ { 9, 1, 1, 3, 151, 4, }, + { 0, 1, 1, 3, 159, 72, }, +- { 2, 1, 1, 3, 159, -128, }, ++ { 2, 1, 1, 3, 159, 4, }, + { 1, 1, 1, 3, 159, 127, }, + { 3, 1, 1, 3, 159, 72, }, + { 4, 1, 1, 3, 159, 66, }, +@@ -27563,32 +43606,32 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 6, 1, 1, 3, 159, 72, }, + { 7, 1, 1, 3, 159, 30, }, + { 8, 1, 1, 3, 159, 72, }, +- { 9, 1, 1, 3, 159, -128, }, +- { 0, 1, 2, 4, 42, 64, }, ++ { 9, 1, 1, 3, 159, 4, }, ++ { 0, 1, 2, 4, 42, 68, }, + { 2, 1, 2, 4, 42, 64, }, + { 1, 1, 2, 4, 42, 64, }, + { 3, 1, 2, 4, 42, 64, }, +- { 4, 1, 2, 4, 42, 68, }, ++ { 4, 1, 2, 4, 42, 60, }, + { 5, 1, 2, 4, 42, 64, }, + { 6, 1, 2, 4, 42, 64, }, + { 7, 1, 2, 4, 42, 54, }, + { 8, 1, 2, 4, 42, 62, }, + { 9, 1, 2, 4, 42, 64, }, +- { 0, 1, 2, 4, 58, 62, }, ++ { 0, 1, 2, 4, 58, 60, }, + { 2, 1, 2, 4, 58, 64, }, + { 1, 1, 2, 4, 58, 64, }, +- { 3, 1, 2, 4, 58, 62, }, +- { 4, 1, 2, 4, 58, 64, }, ++ { 3, 1, 2, 4, 58, 60, }, ++ { 4, 1, 2, 4, 58, 56, }, + { 5, 1, 2, 4, 58, 64, }, + { 6, 1, 2, 4, 58, 62, }, + { 7, 1, 2, 4, 58, 54, }, + { 8, 1, 2, 4, 58, 62, }, + { 9, 1, 2, 4, 58, 64, }, +- { 0, 1, 2, 4, 106, 58, }, ++ { 0, 1, 2, 4, 106, 60, }, + { 2, 1, 2, 4, 106, 64, }, + { 1, 1, 2, 4, 106, 72, }, +- { 3, 1, 2, 4, 106, 58, }, +- { 4, 1, 2, 4, 106, 66, }, ++ { 3, 1, 2, 4, 106, 60, }, ++ { 4, 1, 2, 4, 106, 58, }, + { 5, 1, 2, 4, 106, 64, }, + { 6, 1, 2, 4, 106, 58, }, + { 7, 1, 2, 4, 106, 54, }, +@@ -27606,84 +43649,84 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { + { 9, 1, 2, 4, 122, 127, }, + { 0, 1, 2, 4, 138, 72, }, + { 2, 1, 2, 4, 138, 127, }, +- { 1, 1, 2, 4, 138, 127, }, ++ { 1, 1, 2, 4, 138, 72, }, + { 3, 1, 2, 4, 138, 72, }, +- { 4, 1, 2, 4, 138, 68, }, ++ { 4, 1, 2, 4, 138, 70, }, + { 5, 1, 2, 4, 138, 127, }, + { 6, 1, 2, 4, 138, 72, }, + { 7, 1, 2, 4, 138, 127, }, + { 8, 1, 2, 4, 138, 72, }, + { 9, 1, 2, 4, 138, 127, }, + { 0, 1, 2, 4, 155, 72, }, +- { 2, 1, 2, 4, 155, -128, }, ++ { 2, 1, 2, 4, 155, 28, }, + { 1, 1, 2, 4, 155, 127, }, + { 3, 1, 2, 4, 155, 72, }, +- { 4, 1, 2, 4, 155, 68, }, ++ { 4, 1, 2, 4, 155, 62, }, + { 5, 1, 2, 4, 155, 72, }, + { 6, 1, 2, 4, 155, 72, }, + { 7, 1, 2, 4, 155, 54, }, + { 8, 1, 2, 4, 155, 68, }, +- { 9, 1, 2, 4, 155, -128, }, +- { 0, 1, 2, 5, 42, 54, }, ++ { 9, 1, 2, 4, 155, 28, }, ++ { 0, 1, 2, 5, 42, 56, }, + { 2, 1, 2, 5, 42, 40, }, + { 1, 1, 2, 5, 42, 50, }, + { 3, 1, 2, 5, 42, 40, }, +- { 4, 1, 2, 5, 42, 58, }, ++ { 4, 1, 2, 5, 42, 50, }, + { 5, 1, 2, 5, 42, 40, }, + { 6, 1, 2, 5, 42, 52, }, + { 7, 1, 2, 5, 42, 30, }, + { 8, 1, 2, 5, 42, 50, }, + { 9, 1, 2, 5, 42, 40, }, +- { 0, 1, 2, 5, 58, 52, }, ++ { 0, 1, 2, 5, 58, 54, }, + { 2, 1, 2, 5, 58, 40, }, + { 1, 1, 2, 5, 58, 50, }, + { 3, 1, 2, 5, 58, 40, }, +- { 4, 1, 2, 5, 58, 56, }, ++ { 4, 1, 2, 5, 58, 46, }, + { 5, 1, 2, 5, 58, 40, }, + { 6, 1, 2, 5, 58, 52, }, + { 7, 1, 2, 5, 58, 30, }, + { 8, 1, 2, 5, 58, 52, }, + { 9, 1, 2, 5, 58, 40, }, +- { 0, 1, 2, 5, 106, 50, }, ++ { 0, 1, 2, 5, 106, 48, }, + { 2, 1, 2, 5, 106, 40, }, + { 1, 1, 2, 5, 106, 72, }, +- { 3, 1, 2, 5, 106, 50, }, +- { 4, 1, 2, 5, 106, 56, }, ++ { 3, 1, 2, 5, 106, 48, }, ++ { 4, 1, 2, 5, 106, 50, }, + { 5, 1, 2, 5, 106, 40, }, + { 6, 1, 2, 5, 106, 50, }, + { 7, 1, 2, 5, 106, 30, }, + { 8, 1, 2, 5, 106, 50, }, + { 9, 1, 2, 5, 106, 127, }, +- { 0, 1, 2, 5, 122, 66, }, ++ { 0, 1, 2, 5, 122, 70, }, + { 2, 1, 2, 5, 122, 40, }, + { 1, 1, 2, 5, 122, 72, }, + { 3, 1, 2, 5, 122, 127, }, +- { 4, 1, 2, 5, 122, 56, }, ++ { 4, 1, 2, 5, 122, 62, }, + { 5, 1, 2, 5, 122, 127, }, + { 6, 1, 2, 5, 122, 66, }, + { 7, 1, 2, 5, 122, 30, }, + { 8, 1, 2, 5, 122, 66, }, + { 9, 1, 2, 5, 122, 127, }, +- { 0, 1, 2, 5, 138, 66, }, ++ { 0, 1, 2, 5, 138, 70, }, + { 2, 1, 2, 5, 138, 127, }, +- { 1, 1, 2, 5, 138, 127, }, +- { 3, 1, 2, 5, 138, 66, }, +- { 4, 1, 2, 5, 138, 58, }, ++ { 1, 1, 2, 5, 138, 72, }, ++ { 3, 1, 2, 5, 138, 70, }, ++ { 4, 1, 2, 5, 138, 62, }, + { 5, 1, 2, 5, 138, 127, }, + { 6, 1, 2, 5, 138, 66, }, + { 7, 1, 2, 5, 138, 127, }, + { 8, 1, 2, 5, 138, 66, }, + { 9, 1, 2, 5, 138, 127, }, +- { 0, 1, 2, 5, 155, 62, }, +- { 2, 1, 2, 5, 155, -128, }, ++ { 0, 1, 2, 5, 155, 72, }, ++ { 2, 1, 2, 5, 155, 4, }, + { 1, 1, 2, 5, 155, 127, }, +- { 3, 1, 2, 5, 155, 62, }, +- { 4, 1, 2, 5, 155, 58, }, ++ { 3, 1, 2, 5, 155, 72, }, ++ { 4, 1, 2, 5, 155, 52, }, + { 5, 1, 2, 5, 155, 72, }, + { 6, 1, 2, 5, 155, 62, }, + { 7, 1, 2, 5, 155, 30, }, + { 8, 1, 2, 5, 155, 62, }, +- { 9, 1, 2, 5, 155, -128, }, ++ { 9, 1, 2, 5, 155, 4, }, + }; + + RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type5); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c +index 026ac49ce6e3..e26c6bc82936 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c +@@ -4,7 +4,8 @@ + + #include + #include +-#include "rtw8822ce.h" ++#include "pci.h" ++#include "rtw8822c.h" + + static const struct pci_device_id rtw_8822ce_id_table[] = { + { +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c +new file mode 100644 +index 000000000000..5d68b9aa5fd7 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) Martin Blumenstingl ++ */ ++ ++#include ++#include "sdio_ids.h" ++#include ++#include "main.h" ++#include "rtw8822c.h" ++#include "sdio.h" ++ ++static const struct sdio_device_id rtw_8822cs_id_table[] = { ++ { ++ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, ++ SDIO_DEVICE_ID_REALTEK_RTW8822CS), ++ .driver_data = (kernel_ulong_t)&rtw8822c_hw_spec, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(sdio, rtw_8822cs_id_table); ++ ++static struct sdio_driver rtw_8822cs_driver = { ++ .name = "rtw_8822cs", ++ .probe = rtw_sdio_probe, ++ .remove = rtw_sdio_remove, ++ .id_table = rtw_8822cs_id_table, ++ .drv = { ++ .pm = &rtw_sdio_pm_ops, ++ .shutdown = rtw_sdio_shutdown, ++ } ++}; ++module_sdio_driver(rtw_8822cs_driver); ++ ++MODULE_AUTHOR("Martin Blumenstingl "); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cs driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c +new file mode 100644 +index 000000000000..157d5102a4b1 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include "main.h" ++#include "rtw8822c.h" ++#include "usb.h" ++ ++static const struct usb_device_id rtw_8822cu_id_table[] = { ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82e, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd820, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd82b, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */ ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table); ++ ++static int rtw8822cu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return rtw_usb_probe(intf, id); ++} ++ ++static struct usb_driver rtw_8822cu_driver = { ++ .name = "rtw_8822cu", ++ .id_table = rtw_8822cu_id_table, ++ .probe = rtw8822cu_probe, ++ .disconnect = rtw_usb_disconnect, ++}; ++module_usb_driver(rtw_8822cu_driver); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cu driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c +index 7087e385a9b3..b420a39b167d 100644 +--- a/drivers/net/wireless/realtek/rtw88/rx.c ++++ b/drivers/net/wireless/realtek/rtw88/rx.c +@@ -6,6 +6,7 @@ + #include "rx.h" + #include "ps.h" + #include "debug.h" ++#include "fw.h" + + void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb) +@@ -138,6 +139,13 @@ static void rtw_rx_addr_match(struct rtw_dev *rtwdev, + rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data); + } + ++static void rtw_set_rx_freq_by_pktstat(struct rtw_rx_pkt_stat *pkt_stat, ++ struct ieee80211_rx_status *rx_status) ++{ ++ rx_status->freq = pkt_stat->freq; ++ rx_status->band = pkt_stat->band; ++} ++ + void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, +@@ -148,17 +156,37 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + u8 path; + + memset(rx_status, 0, sizeof(*rx_status)); ++ if (!hw) { ++ rtw_warn(rtwdev, "hw NULL in %s\n", __func__); ++ return; ++ } ++ if (!hw->conf.chandef.chan) { ++ rtw_warn(rtwdev, "hw->conf.chandef.chan NULL in %s\n", __func__); ++ return; ++ } ++ + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; ++ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) && ++ test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) ++ rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status); + if (pkt_stat->crc_err) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (pkt_stat->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + + if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + rx_status->encoding = RX_ENC_VHT; ++#else ++ rx_status->flag |= RX_FLAG_VHT; ++#endif + else if (pkt_stat->rate >= DESC_RATEMCS0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + rx_status->encoding = RX_ENC_HT; ++#else ++ rx_status->flag |= RX_FLAG_VHT; ++#endif + + if (rx_status->band == NL80211_BAND_5GHZ && + pkt_stat->rate >= DESC_RATE6M && +@@ -177,11 +205,23 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + rx_status->mactime = pkt_stat->tsf_low; + + if (pkt_stat->bw == RTW_CHANNEL_WIDTH_80) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + rx_status->bw = RATE_INFO_BW_80; ++#else ++ rx_status->vht_flag |= RX_VHT_FLAG_80MHZ; ++#endif + else if (pkt_stat->bw == RTW_CHANNEL_WIDTH_40) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + rx_status->bw = RATE_INFO_BW_40; ++#else ++ rx_status->flag |= RX_FLAG_40MHZ; ++#endif + else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + rx_status->bw = RATE_INFO_BW_20; ++#else ++ /* What goes here? */ ++#endif + + rx_status->signal = pkt_stat->signal_power; + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { +diff --git a/drivers/net/wireless/realtek/rtw88/sar.c b/drivers/net/wireless/realtek/rtw88/sar.c +new file mode 100644 +index 000000000000..475e79c91f03 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sar.c +@@ -0,0 +1,116 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2021 Realtek Corporation ++ */ ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++#include "sar.h" ++#include "phy.h" ++#include "debug.h" ++ ++s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg) ++{ ++ const struct rtw_hal *hal = &rtwdev->hal; ++ const struct rtw_sar *sar = &hal->sar; ++ ++ switch (sar->src) { ++ default: ++ rtw_warn(rtwdev, "unknown SAR source: %d\n", sar->src); ++ fallthrough; ++ case RTW_SAR_SOURCE_NONE: ++ return (s8)rtwdev->chip->max_power_index; ++ case RTW_SAR_SOURCE_COMMON: ++ return sar->cfg[arg->path][arg->rs].common[arg->sar_band]; ++ } ++} ++ ++static int rtw_apply_sar(struct rtw_dev *rtwdev, const struct rtw_sar *new) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ struct rtw_sar *sar = &hal->sar; ++ ++ if (sar->src != RTW_SAR_SOURCE_NONE && new->src != sar->src) { ++ rtw_warn(rtwdev, "SAR source: %d is in use\n", sar->src); ++ return -EBUSY; ++ } ++ ++ *sar = *new; ++ rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); ++ ++ return 0; ++} ++ ++static s8 rtw_sar_to_phy(struct rtw_dev *rtwdev, u8 fct, s32 sar, ++ const struct rtw_sar_arg *arg) ++{ ++ struct rtw_hal *hal = &rtwdev->hal; ++ u8 txgi = rtwdev->chip->txgi_factor; ++ u8 max = rtwdev->chip->max_power_index; ++ s32 tmp; ++ s8 base; ++ ++ tmp = fct > txgi ? sar >> (fct - txgi) : sar << (txgi - fct); ++ base = arg->sar_band == RTW_SAR_BAND_0 ? ++ hal->tx_pwr_by_rate_base_2g[arg->path][arg->rs] : ++ hal->tx_pwr_by_rate_base_5g[arg->path][arg->rs]; ++ ++ return (s8)clamp_t(s32, tmp, -max - 1, max) - base; ++} ++ ++static const struct cfg80211_sar_freq_ranges rtw_common_sar_freq_ranges[] = { ++ [RTW_SAR_BAND_0] = { .start_freq = 2412, .end_freq = 2484, }, ++ [RTW_SAR_BAND_1] = { .start_freq = 5180, .end_freq = 5320, }, ++ [RTW_SAR_BAND_3] = { .start_freq = 5500, .end_freq = 5720, }, ++ [RTW_SAR_BAND_4] = { .start_freq = 5745, .end_freq = 5825, }, ++}; ++ ++const struct cfg80211_sar_capa rtw_sar_capa = { ++ .type = NL80211_SAR_TYPE_POWER, ++ .num_freq_ranges = RTW_SAR_BAND_NR, ++ .freq_ranges = rtw_common_sar_freq_ranges, ++}; ++ ++int rtw_set_sar_specs(struct rtw_dev *rtwdev, ++ const struct cfg80211_sar_specs *sar) ++{ ++ struct rtw_sar_arg arg = {0}; ++ struct rtw_sar new = {0}; ++ u32 idx, i, j, k; ++ s32 power; ++ s8 val; ++ ++ if (sar->type != NL80211_SAR_TYPE_POWER) ++ return -EINVAL; ++ ++ memset(&new, rtwdev->chip->max_power_index, sizeof(new)); ++ new.src = RTW_SAR_SOURCE_COMMON; ++ ++ for (i = 0; i < sar->num_sub_specs; i++) { ++ idx = sar->sub_specs[i].freq_range_index; ++ if (idx >= RTW_SAR_BAND_NR) ++ return -EINVAL; ++ ++ power = sar->sub_specs[i].power; ++ rtw_dbg(rtwdev, RTW_DBG_REGD, "On freq %u to %u, set SAR %d in 1/%lu dBm\n", ++ rtw_common_sar_freq_ranges[idx].start_freq, ++ rtw_common_sar_freq_ranges[idx].end_freq, ++ power, BIT(RTW_COMMON_SAR_FCT)); ++ ++ for (j = 0; j < RTW_RF_PATH_MAX; j++) { ++ for (k = 0; k < RTW_RATE_SECTION_MAX; k++) { ++ arg = (struct rtw_sar_arg){ ++ .sar_band = idx, ++ .path = j, ++ .rs = k, ++ }; ++ val = rtw_sar_to_phy(rtwdev, RTW_COMMON_SAR_FCT, ++ power, &arg); ++ new.cfg[j][k].common[idx] = val; ++ } ++ } ++ } ++ ++ return rtw_apply_sar(rtwdev, &new); ++} ++#endif ++ +diff --git a/drivers/net/wireless/realtek/rtw88/sar.h b/drivers/net/wireless/realtek/rtw88/sar.h +new file mode 100644 +index 000000000000..75f6118ef92f +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sar.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2018-2021 Realtek Corporation ++ */ ++ ++#include "main.h" ++ ++/* NL80211_SAR_TYPE_POWER means unit is in 0.25 dBm, ++ * where 0.25 = 1/4 = 2^(-2), so make factor 2. ++ */ ++#define RTW_COMMON_SAR_FCT 2 ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++struct rtw_sar_arg { ++ u8 sar_band; ++ u8 path; ++ u8 rs; ++}; ++ ++extern const struct cfg80211_sar_capa rtw_sar_capa; ++ ++s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg); ++int rtw_set_sar_specs(struct rtw_dev *rtwdev, ++ const struct cfg80211_sar_specs *sar); ++#endif ++ +diff --git a/drivers/net/wireless/realtek/rtw88/sch_generic.h b/drivers/net/wireless/realtek/rtw88/sch_generic.h +new file mode 100644 +index 000000000000..241a0c597b3c +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sch_generic.h +@@ -0,0 +1,849 @@ ++#ifndef __NET_SCHED_GENERIC_H ++#define __NET_SCHED_GENERIC_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct Qdisc_ops; ++struct qdisc_walker; ++struct tcf_walker; ++struct module; ++ ++struct qdisc_rate_table { ++ struct tc_ratespec rate; ++ u32 data[256]; ++ struct qdisc_rate_table *next; ++ int refcnt; ++}; ++ ++enum qdisc_state_t { ++ __QDISC_STATE_SCHED, ++ __QDISC_STATE_DEACTIVATED, ++}; ++ ++struct qdisc_size_table { ++ struct rcu_head rcu; ++ struct list_head list; ++ struct tc_sizespec szopts; ++ int refcnt; ++ u16 data[]; ++}; ++ ++/* similar to sk_buff_head, but skb->prev pointer is undefined. */ ++struct qdisc_skb_head { ++ struct sk_buff *head; ++ struct sk_buff *tail; ++ __u32 qlen; ++ spinlock_t lock; ++}; ++ ++struct Qdisc { ++ int (*enqueue)(struct sk_buff *skb, ++ struct Qdisc *sch, ++ struct sk_buff **to_free); ++ struct sk_buff * (*dequeue)(struct Qdisc *sch); ++ unsigned int flags; ++#define TCQ_F_BUILTIN 1 ++#define TCQ_F_INGRESS 2 ++#define TCQ_F_CAN_BYPASS 4 ++#define TCQ_F_MQROOT 8 ++#define TCQ_F_ONETXQUEUE 0x10 /* dequeue_skb() can assume all skbs are for ++ * q->dev_queue : It can test ++ * netif_xmit_frozen_or_stopped() before ++ * dequeueing next packet. ++ * Its true for MQ/MQPRIO slaves, or non ++ * multiqueue device. ++ */ ++#define TCQ_F_WARN_NONWC (1 << 16) ++#define TCQ_F_CPUSTATS 0x20 /* run using percpu statistics */ ++#define TCQ_F_NOPARENT 0x40 /* root of its hierarchy : ++ * qdisc_tree_decrease_qlen() should stop. ++ */ ++ u32 limit; ++ const struct Qdisc_ops *ops; ++ struct qdisc_size_table __rcu *stab; ++ struct hlist_node hash; ++ u32 handle; ++ u32 parent; ++ void *u32_node; ++ ++ struct netdev_queue *dev_queue; ++ ++ struct net_rate_estimator __rcu *rate_est; ++ struct gnet_stats_basic_cpu __percpu *cpu_bstats; ++ struct gnet_stats_queue __percpu *cpu_qstats; ++ ++ /* ++ * For performance sake on SMP, we put highly modified fields at the end ++ */ ++ struct sk_buff *gso_skb ____cacheline_aligned_in_smp; ++ struct qdisc_skb_head q; ++ struct gnet_stats_basic_packed bstats; ++ seqcount_t running; ++ struct gnet_stats_queue qstats; ++ unsigned long state; ++ struct Qdisc *next_sched; ++ struct sk_buff *skb_bad_txq; ++ struct rcu_head rcu_head; ++ int padded; ++ atomic_t refcnt; ++ ++ spinlock_t busylock ____cacheline_aligned_in_smp; ++}; ++ ++static inline bool qdisc_is_running(const struct Qdisc *qdisc) ++{ ++ return (raw_read_seqcount(&qdisc->running) & 1) ? true : false; ++} ++ ++static inline bool qdisc_run_begin(struct Qdisc *qdisc) ++{ ++ if (qdisc_is_running(qdisc)) ++ return false; ++ /* Variant of write_seqcount_begin() telling lockdep a trylock ++ * was attempted. ++ */ ++ raw_write_seqcount_begin(&qdisc->running); ++ seqcount_acquire(&qdisc->running.dep_map, 0, 1, _RET_IP_); ++ return true; ++} ++ ++static inline void qdisc_run_end(struct Qdisc *qdisc) ++{ ++ write_seqcount_end(&qdisc->running); ++} ++ ++static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) ++{ ++ return qdisc->flags & TCQ_F_ONETXQUEUE; ++} ++ ++static inline int qdisc_avail_bulklimit(const struct netdev_queue *txq) ++{ ++#ifdef CONFIG_BQL ++ /* Non-BQL migrated drivers will return 0, too. */ ++ return dql_avail(&txq->dql); ++#else ++ return 0; ++#endif ++} ++ ++struct Qdisc_class_ops { ++ /* Child qdisc manipulation */ ++ struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); ++ int (*graft)(struct Qdisc *, unsigned long cl, ++ struct Qdisc *, struct Qdisc **); ++ struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); ++ void (*qlen_notify)(struct Qdisc *, unsigned long); ++ ++ /* Class manipulation routines */ ++ unsigned long (*get)(struct Qdisc *, u32 classid); ++ void (*put)(struct Qdisc *, unsigned long); ++ int (*change)(struct Qdisc *, u32, u32, ++ struct nlattr **, unsigned long *); ++ int (*delete)(struct Qdisc *, unsigned long); ++ void (*walk)(struct Qdisc *, struct qdisc_walker * arg); ++ ++ /* Filter manipulation */ ++ struct tcf_proto __rcu ** (*tcf_chain)(struct Qdisc *, unsigned long); ++ bool (*tcf_cl_offload)(u32 classid); ++ unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, ++ u32 classid); ++ void (*unbind_tcf)(struct Qdisc *, unsigned long); ++ ++ /* rtnetlink specific */ ++ int (*dump)(struct Qdisc *, unsigned long, ++ struct sk_buff *skb, struct tcmsg*); ++ int (*dump_stats)(struct Qdisc *, unsigned long, ++ struct gnet_dump *); ++}; ++ ++struct Qdisc_ops { ++ struct Qdisc_ops *next; ++ const struct Qdisc_class_ops *cl_ops; ++ char id[IFNAMSIZ]; ++ int priv_size; ++ ++ int (*enqueue)(struct sk_buff *skb, ++ struct Qdisc *sch, ++ struct sk_buff **to_free); ++ struct sk_buff * (*dequeue)(struct Qdisc *); ++ struct sk_buff * (*peek)(struct Qdisc *); ++ ++ int (*init)(struct Qdisc *, struct nlattr *arg); ++ void (*reset)(struct Qdisc *); ++ void (*destroy)(struct Qdisc *); ++ int (*change)(struct Qdisc *, struct nlattr *arg); ++ void (*attach)(struct Qdisc *); ++ ++ int (*dump)(struct Qdisc *, struct sk_buff *); ++ int (*dump_stats)(struct Qdisc *, struct gnet_dump *); ++ ++ struct module *owner; ++}; ++ ++ ++struct tcf_result { ++ unsigned long class; ++ u32 classid; ++}; ++ ++struct tcf_proto_ops { ++ struct list_head head; ++ char kind[IFNAMSIZ]; ++ ++ int (*classify)(struct sk_buff *, ++ const struct tcf_proto *, ++ struct tcf_result *); ++ int (*init)(struct tcf_proto*); ++ bool (*destroy)(struct tcf_proto*, bool); ++ ++ unsigned long (*get)(struct tcf_proto*, u32 handle); ++ int (*change)(struct net *net, struct sk_buff *, ++ struct tcf_proto*, unsigned long, ++ u32 handle, struct nlattr **, ++ unsigned long *, bool); ++ int (*delete)(struct tcf_proto*, unsigned long); ++ void (*walk)(struct tcf_proto*, struct tcf_walker *arg); ++ ++ /* rtnetlink specific */ ++ int (*dump)(struct net*, struct tcf_proto*, unsigned long, ++ struct sk_buff *skb, struct tcmsg*); ++ ++ struct module *owner; ++}; ++ ++struct tcf_proto { ++ /* Fast access part */ ++ struct tcf_proto __rcu *next; ++ void __rcu *root; ++ int (*classify)(struct sk_buff *, ++ const struct tcf_proto *, ++ struct tcf_result *); ++ __be16 protocol; ++ ++ /* All the rest */ ++ u32 prio; ++ u32 classid; ++ struct Qdisc *q; ++ void *data; ++ const struct tcf_proto_ops *ops; ++ struct rcu_head rcu; ++}; ++ ++struct qdisc_skb_cb { ++ unsigned int pkt_len; ++ u16 slave_dev_queue_mapping; ++ u16 tc_classid; ++#define QDISC_CB_PRIV_LEN 20 ++ unsigned char data[QDISC_CB_PRIV_LEN]; ++}; ++ ++static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ struct qdisc_skb_cb *qcb; ++ ++ BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); ++ BUILD_BUG_ON(sizeof(qcb->data) < sz); ++#endif ++} ++ ++static inline int qdisc_qlen(const struct Qdisc *q) ++{ ++ return q->q.qlen; ++} ++ ++static inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb) ++{ ++ return (struct qdisc_skb_cb *)skb->cb; ++} ++ ++static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc) ++{ ++ return &qdisc->q.lock; ++} ++ ++static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc) ++{ ++ struct Qdisc *q = rcu_dereference_rtnl(qdisc->dev_queue->qdisc); ++ ++ return q; ++} ++ ++static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc) ++{ ++ return qdisc->dev_queue->qdisc_sleeping; ++} ++ ++/* The qdisc root lock is a mechanism by which to top level ++ * of a qdisc tree can be locked from any qdisc node in the ++ * forest. This allows changing the configuration of some ++ * aspect of the qdisc tree while blocking out asynchronous ++ * qdisc access in the packet processing paths. ++ * ++ * It is only legal to do this when the root will not change ++ * on us. Otherwise we'll potentially lock the wrong qdisc ++ * root. This is enforced by holding the RTNL semaphore, which ++ * all users of this lock accessor must do. ++ */ ++static inline spinlock_t *qdisc_root_lock(const struct Qdisc *qdisc) ++{ ++ struct Qdisc *root = qdisc_root(qdisc); ++ ++ ASSERT_RTNL(); ++ return qdisc_lock(root); ++} ++ ++static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc) ++{ ++ struct Qdisc *root = qdisc_root_sleeping(qdisc); ++ ++ ASSERT_RTNL(); ++ return qdisc_lock(root); ++} ++ ++static inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc) ++{ ++ struct Qdisc *root = qdisc_root_sleeping(qdisc); ++ ++ ASSERT_RTNL(); ++ return &root->running; ++} ++ ++static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc) ++{ ++ return qdisc->dev_queue->dev; ++} ++ ++static inline void sch_tree_lock(const struct Qdisc *q) ++{ ++ spin_lock_bh(qdisc_root_sleeping_lock(q)); ++} ++ ++static inline void sch_tree_unlock(const struct Qdisc *q) ++{ ++ spin_unlock_bh(qdisc_root_sleeping_lock(q)); ++} ++ ++#define tcf_tree_lock(tp) sch_tree_lock((tp)->q) ++#define tcf_tree_unlock(tp) sch_tree_unlock((tp)->q) ++ ++extern struct Qdisc noop_qdisc; ++extern struct Qdisc_ops noop_qdisc_ops; ++extern struct Qdisc_ops pfifo_fast_ops; ++extern struct Qdisc_ops mq_qdisc_ops; ++extern struct Qdisc_ops noqueue_qdisc_ops; ++extern const struct Qdisc_ops *default_qdisc_ops; ++static inline const struct Qdisc_ops * ++get_default_qdisc_ops(const struct net_device *dev, int ntx) ++{ ++ return ntx < dev->real_num_tx_queues ? ++ default_qdisc_ops : &pfifo_fast_ops; ++} ++ ++struct Qdisc_class_common { ++ u32 classid; ++ struct hlist_node hnode; ++}; ++ ++struct Qdisc_class_hash { ++ struct hlist_head *hash; ++ unsigned int hashsize; ++ unsigned int hashmask; ++ unsigned int hashelems; ++}; ++ ++static inline unsigned int qdisc_class_hash(u32 id, u32 mask) ++{ ++ id ^= id >> 8; ++ id ^= id >> 4; ++ return id & mask; ++} ++ ++static inline struct Qdisc_class_common * ++qdisc_class_find(const struct Qdisc_class_hash *hash, u32 id) ++{ ++ struct Qdisc_class_common *cl; ++ unsigned int h; ++ ++ h = qdisc_class_hash(id, hash->hashmask); ++ hlist_for_each_entry(cl, &hash->hash[h], hnode) { ++ if (cl->classid == id) ++ return cl; ++ } ++ return NULL; ++} ++ ++int qdisc_class_hash_init(struct Qdisc_class_hash *); ++void qdisc_class_hash_insert(struct Qdisc_class_hash *, ++ struct Qdisc_class_common *); ++void qdisc_class_hash_remove(struct Qdisc_class_hash *, ++ struct Qdisc_class_common *); ++void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); ++void qdisc_class_hash_destroy(struct Qdisc_class_hash *); ++ ++void dev_init_scheduler(struct net_device *dev); ++void dev_shutdown(struct net_device *dev); ++void dev_activate(struct net_device *dev); ++void dev_deactivate(struct net_device *dev); ++void dev_deactivate_many(struct list_head *head); ++struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, ++ struct Qdisc *qdisc); ++void qdisc_reset(struct Qdisc *qdisc); ++void qdisc_destroy(struct Qdisc *qdisc); ++void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n, ++ unsigned int len); ++struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, ++ const struct Qdisc_ops *ops); ++struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, ++ const struct Qdisc_ops *ops, u32 parentid); ++void __qdisc_calculate_pkt_len(struct sk_buff *skb, ++ const struct qdisc_size_table *stab); ++bool tcf_destroy(struct tcf_proto *tp, bool force); ++void tcf_destroy_chain(struct tcf_proto __rcu **fl); ++int skb_do_redirect(struct sk_buff *); ++ ++static inline bool skb_at_tc_ingress(const struct sk_buff *skb) ++{ ++#ifdef CONFIG_NET_CLS_ACT ++ return G_TC_AT(skb->tc_verd) & AT_INGRESS; ++#else ++ return false; ++#endif ++} ++ ++/* Reset all TX qdiscs greater then index of a device. */ ++static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) ++{ ++ struct Qdisc *qdisc; ++ ++ for (; i < dev->num_tx_queues; i++) { ++ qdisc = rtnl_dereference(netdev_get_tx_queue(dev, i)->qdisc); ++ if (qdisc) { ++ spin_lock_bh(qdisc_lock(qdisc)); ++ qdisc_reset(qdisc); ++ spin_unlock_bh(qdisc_lock(qdisc)); ++ } ++ } ++} ++ ++static inline void qdisc_reset_all_tx(struct net_device *dev) ++{ ++ qdisc_reset_all_tx_gt(dev, 0); ++} ++ ++/* Are all TX queues of the device empty? */ ++static inline bool qdisc_all_tx_empty(const struct net_device *dev) ++{ ++ unsigned int i; ++ ++ rcu_read_lock(); ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ struct netdev_queue *txq = netdev_get_tx_queue(dev, i); ++ const struct Qdisc *q = rcu_dereference(txq->qdisc); ++ ++ if (q->q.qlen) { ++ rcu_read_unlock(); ++ return false; ++ } ++ } ++ rcu_read_unlock(); ++ return true; ++} ++ ++/* Are any of the TX qdiscs changing? */ ++static inline bool qdisc_tx_changing(const struct net_device *dev) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ struct netdev_queue *txq = netdev_get_tx_queue(dev, i); ++ if (rcu_access_pointer(txq->qdisc) != txq->qdisc_sleeping) ++ return true; ++ } ++ return false; ++} ++ ++/* Is the device using the noop qdisc on all queues? */ ++static inline bool qdisc_tx_is_noop(const struct net_device *dev) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ struct netdev_queue *txq = netdev_get_tx_queue(dev, i); ++ if (rcu_access_pointer(txq->qdisc) != &noop_qdisc) ++ return false; ++ } ++ return true; ++} ++ ++static inline unsigned int qdisc_pkt_len(const struct sk_buff *skb) ++{ ++ return qdisc_skb_cb(skb)->pkt_len; ++} ++ ++/* additional qdisc xmit flags (NET_XMIT_MASK in linux/netdevice.h) */ ++enum net_xmit_qdisc_t { ++ __NET_XMIT_STOLEN = 0x00010000, ++ __NET_XMIT_BYPASS = 0x00020000, ++}; ++ ++#ifdef CONFIG_NET_CLS_ACT ++#define net_xmit_drop_count(e) ((e) & __NET_XMIT_STOLEN ? 0 : 1) ++#else ++#define net_xmit_drop_count(e) (1) ++#endif ++ ++static inline void qdisc_calculate_pkt_len(struct sk_buff *skb, ++ const struct Qdisc *sch) ++{ ++#ifdef CONFIG_NET_SCHED ++ struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab); ++ ++ if (stab) ++ __qdisc_calculate_pkt_len(skb, stab); ++#endif ++} ++ ++static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, ++ struct sk_buff **to_free) ++{ ++ qdisc_calculate_pkt_len(skb, sch); ++ return sch->enqueue(skb, sch, to_free); ++} ++ ++static inline bool qdisc_is_percpu_stats(const struct Qdisc *q) ++{ ++ return q->flags & TCQ_F_CPUSTATS; ++} ++ ++static inline void _bstats_update(struct gnet_stats_basic_packed *bstats, ++ __u64 bytes, __u32 packets) ++{ ++ bstats->bytes += bytes; ++ bstats->packets += packets; ++} ++ ++static inline void bstats_update(struct gnet_stats_basic_packed *bstats, ++ const struct sk_buff *skb) ++{ ++ _bstats_update(bstats, ++ qdisc_pkt_len(skb), ++ skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1); ++} ++ ++static inline void _bstats_cpu_update(struct gnet_stats_basic_cpu *bstats, ++ __u64 bytes, __u32 packets) ++{ ++ u64_stats_update_begin(&bstats->syncp); ++ _bstats_update(&bstats->bstats, bytes, packets); ++ u64_stats_update_end(&bstats->syncp); ++} ++ ++static inline void bstats_cpu_update(struct gnet_stats_basic_cpu *bstats, ++ const struct sk_buff *skb) ++{ ++ u64_stats_update_begin(&bstats->syncp); ++ bstats_update(&bstats->bstats, skb); ++ u64_stats_update_end(&bstats->syncp); ++} ++ ++static inline void qdisc_bstats_cpu_update(struct Qdisc *sch, ++ const struct sk_buff *skb) ++{ ++ bstats_cpu_update(this_cpu_ptr(sch->cpu_bstats), skb); ++} ++ ++static inline void qdisc_bstats_update(struct Qdisc *sch, ++ const struct sk_buff *skb) ++{ ++ bstats_update(&sch->bstats, skb); ++} ++ ++static inline void qdisc_qstats_backlog_dec(struct Qdisc *sch, ++ const struct sk_buff *skb) ++{ ++ sch->qstats.backlog -= qdisc_pkt_len(skb); ++} ++ ++static inline void qdisc_qstats_backlog_inc(struct Qdisc *sch, ++ const struct sk_buff *skb) ++{ ++ sch->qstats.backlog += qdisc_pkt_len(skb); ++} ++ ++static inline void __qdisc_qstats_drop(struct Qdisc *sch, int count) ++{ ++ sch->qstats.drops += count; ++} ++ ++static inline void qstats_drop_inc(struct gnet_stats_queue *qstats) ++{ ++ qstats->drops++; ++} ++ ++static inline void qstats_overlimit_inc(struct gnet_stats_queue *qstats) ++{ ++ qstats->overlimits++; ++} ++ ++static inline void qdisc_qstats_drop(struct Qdisc *sch) ++{ ++ qstats_drop_inc(&sch->qstats); ++} ++ ++static inline void qdisc_qstats_cpu_drop(struct Qdisc *sch) ++{ ++ this_cpu_inc(sch->cpu_qstats->drops); ++} ++ ++static inline void qdisc_qstats_overlimit(struct Qdisc *sch) ++{ ++ sch->qstats.overlimits++; ++} ++ ++static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh) ++{ ++ qh->head = NULL; ++ qh->tail = NULL; ++ qh->qlen = 0; ++} ++ ++static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, ++ struct qdisc_skb_head *qh) ++{ ++ struct sk_buff *last = qh->tail; ++ ++ if (last) { ++ skb->next = NULL; ++ last->next = skb; ++ qh->tail = skb; ++ } else { ++ qh->tail = skb; ++ qh->head = skb; ++ } ++ qh->qlen++; ++ qdisc_qstats_backlog_inc(sch, skb); ++ ++ return NET_XMIT_SUCCESS; ++} ++ ++static inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch) ++{ ++ return __qdisc_enqueue_tail(skb, sch, &sch->q); ++} ++ ++static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh) ++{ ++ struct sk_buff *skb = qh->head; ++ ++ if (likely(skb != NULL)) { ++ qh->head = skb->next; ++ qh->qlen--; ++ if (qh->head == NULL) ++ qh->tail = NULL; ++ skb->next = NULL; ++ } ++ ++ return skb; ++} ++ ++static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) ++{ ++ struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); ++ ++ if (likely(skb != NULL)) { ++ qdisc_qstats_backlog_dec(sch, skb); ++ qdisc_bstats_update(sch, skb); ++ } ++ ++ return skb; ++} ++ ++/* Instead of calling kfree_skb() while root qdisc lock is held, ++ * queue the skb for future freeing at end of __dev_xmit_skb() ++ */ ++static inline void __qdisc_drop(struct sk_buff *skb, struct sk_buff **to_free) ++{ ++ skb->next = *to_free; ++ *to_free = skb; ++} ++ ++static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch, ++ struct qdisc_skb_head *qh, ++ struct sk_buff **to_free) ++{ ++ struct sk_buff *skb = __qdisc_dequeue_head(qh); ++ ++ if (likely(skb != NULL)) { ++ unsigned int len = qdisc_pkt_len(skb); ++ ++ qdisc_qstats_backlog_dec(sch, skb); ++ __qdisc_drop(skb, to_free); ++ return len; ++ } ++ ++ return 0; ++} ++ ++static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch, ++ struct sk_buff **to_free) ++{ ++ return __qdisc_queue_drop_head(sch, &sch->q, to_free); ++} ++ ++static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) ++{ ++ const struct qdisc_skb_head *qh = &sch->q; ++ ++ return qh->head; ++} ++ ++/* generic pseudo peek method for non-work-conserving qdisc */ ++static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch) ++{ ++ /* we can reuse ->gso_skb because peek isn't called for root qdiscs */ ++ if (!sch->gso_skb) { ++ sch->gso_skb = sch->dequeue(sch); ++ if (sch->gso_skb) { ++ /* it's still part of the queue */ ++ qdisc_qstats_backlog_inc(sch, sch->gso_skb); ++ sch->q.qlen++; ++ } ++ } ++ ++ return sch->gso_skb; ++} ++ ++/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ ++static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) ++{ ++ struct sk_buff *skb = sch->gso_skb; ++ ++ if (skb) { ++ sch->gso_skb = NULL; ++ qdisc_qstats_backlog_dec(sch, skb); ++ sch->q.qlen--; ++ } else { ++ skb = sch->dequeue(sch); ++ } ++ ++ return skb; ++} ++ ++static inline void __qdisc_reset_queue(struct qdisc_skb_head *qh) ++{ ++ /* ++ * We do not know the backlog in bytes of this list, it ++ * is up to the caller to correct it ++ */ ++ ASSERT_RTNL(); ++ if (qh->qlen) { ++ rtnl_kfree_skbs(qh->head, qh->tail); ++ ++ qh->head = NULL; ++ qh->tail = NULL; ++ qh->qlen = 0; ++ } ++} ++ ++static inline void qdisc_reset_queue(struct Qdisc *sch) ++{ ++ __qdisc_reset_queue(&sch->q); ++ sch->qstats.backlog = 0; ++} ++ ++static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, ++ struct Qdisc **pold) ++{ ++ struct Qdisc *old; ++ ++ sch_tree_lock(sch); ++ old = *pold; ++ *pold = new; ++ if (old != NULL) { ++ qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog); ++ qdisc_reset(old); ++ } ++ sch_tree_unlock(sch); ++ ++ return old; ++} ++ ++static inline void rtnl_qdisc_drop(struct sk_buff *skb, struct Qdisc *sch) ++{ ++ rtnl_kfree_skbs(skb, skb); ++ qdisc_qstats_drop(sch); ++} ++ ++ ++static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch, ++ struct sk_buff **to_free) ++{ ++ __qdisc_drop(skb, to_free); ++ qdisc_qstats_drop(sch); ++ ++ return NET_XMIT_DROP; ++} ++ ++/* Length to Time (L2T) lookup in a qdisc_rate_table, to determine how ++ long it will take to send a packet given its size. ++ */ ++static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen) ++{ ++ int slot = pktlen + rtab->rate.cell_align + rtab->rate.overhead; ++ if (slot < 0) ++ slot = 0; ++ slot >>= rtab->rate.cell_log; ++ if (slot > 255) ++ return rtab->data[255]*(slot >> 8) + rtab->data[slot & 0xFF]; ++ return rtab->data[slot]; ++} ++ ++struct psched_ratecfg { ++ u64 rate_bytes_ps; /* bytes per second */ ++ u32 mult; ++ u16 overhead; ++ u8 linklayer; ++ u8 shift; ++}; ++ ++static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, ++ unsigned int len) ++{ ++ len += r->overhead; ++ ++ if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) ++ return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift; ++ ++ return ((u64)len * r->mult) >> r->shift; ++} ++ ++void psched_ratecfg_precompute(struct psched_ratecfg *r, ++ const struct tc_ratespec *conf, ++ u64 rate64); ++ ++static inline void psched_ratecfg_getrate(struct tc_ratespec *res, ++ const struct psched_ratecfg *r) ++{ ++ memset(res, 0, sizeof(*res)); ++ ++ /* legacy struct tc_ratespec has a 32bit @rate field ++ * Qdisc using 64bit rate should add new attributes ++ * in order to maintain compatibility. ++ */ ++ res->rate = min_t(u64, r->rate_bytes_ps, ~0U); ++ ++ res->overhead = r->overhead; ++ res->linklayer = (r->linklayer & TC_LINKLAYER_MASK); ++} ++ ++#endif +diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c +new file mode 100644 +index 000000000000..0cae5746f540 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sdio.c +@@ -0,0 +1,1425 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright (C) 2021 Martin Blumenstingl ++ * Copyright (C) 2021 Jernej Skrabec ++ * ++ * Based on rtw88/pci.c: ++ * Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include ++#include "main.h" ++#include "debug.h" ++#include "fw.h" ++#include "ps.h" ++#include "reg.h" ++#include "rx.h" ++#include "sdio.h" ++#include "tx.h" ++ ++#define RTW_SDIO_INDIRECT_RW_RETRIES 50 ++ ++static bool rtw_sdio_is_bus_addr(u32 addr) ++{ ++ return !!(addr & RTW_SDIO_BUS_MSK); ++} ++ ++static bool rtw_sdio_bus_claim_needed(struct rtw_sdio *rtwsdio) ++{ ++ return !rtwsdio->irq_thread || ++ rtwsdio->irq_thread != current; ++} ++ ++static u32 rtw_sdio_to_bus_offset(struct rtw_dev *rtwdev, u32 addr) ++{ ++ switch (addr & RTW_SDIO_BUS_MSK) { ++ case WLAN_IOREG_OFFSET: ++ addr &= WLAN_IOREG_REG_MSK; ++ addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_MAC_REG); ++ break; ++ case SDIO_LOCAL_OFFSET: ++ addr &= SDIO_LOCAL_REG_MSK; ++ addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_SDIO_REG); ++ break; ++ default: ++ rtw_warn(rtwdev, "Cannot convert addr 0x%08x to bus offset", ++ addr); ++ } ++ ++ return addr; ++} ++ ++static bool rtw_sdio_use_memcpy_io(struct rtw_dev *rtwdev, u32 addr, ++ u8 alignment) ++{ ++ return IS_ALIGNED(addr, alignment) && ++ test_bit(RTW_FLAG_POWERON, rtwdev->flags); ++} ++ ++static void rtw_sdio_writel(struct rtw_dev *rtwdev, u32 val, u32 addr, ++ int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u8 buf[4]; ++ int i; ++ ++ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 4)) { ++ sdio_writel(rtwsdio->sdio_func, val, addr, err_ret); ++ return; ++ } ++ ++ *(__le32 *)buf = cpu_to_le32(val); ++ ++ for (i = 0; i < 4; i++) { ++ sdio_writeb(rtwsdio->sdio_func, buf[i], addr + i, err_ret); ++ if (*err_ret) ++ return; ++ } ++} ++ ++static void rtw_sdio_writew(struct rtw_dev *rtwdev, u16 val, u32 addr, ++ int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u8 buf[2]; ++ int i; ++ ++ *(__le16 *)buf = cpu_to_le16(val); ++ ++ for (i = 0; i < 2; i++) { ++ sdio_writeb(rtwsdio->sdio_func, buf[i], addr + i, err_ret); ++ if (*err_ret) ++ return; ++ } ++} ++ ++static u32 rtw_sdio_readl(struct rtw_dev *rtwdev, u32 addr, int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u8 buf[4]; ++ int i; ++ ++ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 4)) ++ return sdio_readl(rtwsdio->sdio_func, addr, err_ret); ++ ++ for (i = 0; i < 4; i++) { ++ buf[i] = sdio_readb(rtwsdio->sdio_func, addr + i, err_ret); ++ if (*err_ret) ++ return 0; ++ } ++ ++ return le32_to_cpu(*(__le32 *)buf); ++} ++ ++static u16 rtw_sdio_readw(struct rtw_dev *rtwdev, u32 addr, int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u8 buf[2]; ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ buf[i] = sdio_readb(rtwsdio->sdio_func, addr + i, err_ret); ++ if (*err_ret) ++ return 0; ++ } ++ ++ return le16_to_cpu(*(__le16 *)buf); ++} ++ ++static u32 rtw_sdio_to_io_address(struct rtw_dev *rtwdev, u32 addr, ++ bool direct) ++{ ++ if (!direct) ++ return addr; ++ ++ if (!rtw_sdio_is_bus_addr(addr)) ++ addr |= WLAN_IOREG_OFFSET; ++ ++ return rtw_sdio_to_bus_offset(rtwdev, addr); ++} ++ ++static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr) ++{ ++ return !rtw_sdio_is_sdio30_supported(rtwdev) || ++ rtw_sdio_is_bus_addr(addr); ++} ++ ++static int rtw_sdio_indirect_reg_cfg(struct rtw_dev *rtwdev, u32 addr, u32 cfg) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ unsigned int retry; ++ u32 reg_cfg; ++ int ret; ++ u8 tmp; ++ ++ reg_cfg = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_CFG); ++ ++ rtw_sdio_writel(rtwdev, addr | cfg | BIT_SDIO_INDIRECT_REG_CFG_UNK20, ++ reg_cfg, &ret); ++ if (ret) ++ return ret; ++ ++ for (retry = 0; retry < RTW_SDIO_INDIRECT_RW_RETRIES; retry++) { ++ tmp = sdio_readb(rtwsdio->sdio_func, reg_cfg + 2, &ret); ++ if (!ret && (tmp & BIT(4))) ++ return 0; ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static u8 rtw_sdio_indirect_read8(struct rtw_dev *rtwdev, u32 addr, ++ int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u32 reg_data; ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_READ); ++ if (*err_ret) ++ return 0; ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ return sdio_readb(rtwsdio->sdio_func, reg_data, err_ret); ++} ++ ++static int rtw_sdio_indirect_read_bytes(struct rtw_dev *rtwdev, u32 addr, ++ u8 *buf, int count) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < count; i++) { ++ buf[i] = rtw_sdio_indirect_read8(rtwdev, addr + i, &ret); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++ ++static u16 rtw_sdio_indirect_read16(struct rtw_dev *rtwdev, u32 addr, ++ int *err_ret) ++{ ++ u32 reg_data; ++ u8 buf[2]; ++ ++ if (!IS_ALIGNED(addr, 2)) { ++ *err_ret = rtw_sdio_indirect_read_bytes(rtwdev, addr, buf, 2); ++ if (*err_ret) ++ return 0; ++ ++ return le16_to_cpu(*(__le16 *)buf); ++ } ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_READ); ++ if (*err_ret) ++ return 0; ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ return rtw_sdio_readw(rtwdev, reg_data, err_ret); ++} ++ ++static u32 rtw_sdio_indirect_read32(struct rtw_dev *rtwdev, u32 addr, ++ int *err_ret) ++{ ++ u32 reg_data; ++ u8 buf[4]; ++ ++ if (!IS_ALIGNED(addr, 4)) { ++ *err_ret = rtw_sdio_indirect_read_bytes(rtwdev, addr, buf, 4); ++ if (*err_ret) ++ return 0; ++ ++ return le32_to_cpu(*(__le32 *)buf); ++ } ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_READ); ++ if (*err_ret) ++ return 0; ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ return rtw_sdio_readl(rtwdev, reg_data, err_ret); ++} ++ ++static u8 rtw_sdio_read8(struct rtw_dev *rtwdev, u32 addr) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ int ret; ++ u8 val; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ val = sdio_readb(rtwsdio->sdio_func, addr, &ret); ++ else ++ val = rtw_sdio_indirect_read8(rtwdev, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio read8 failed (0x%x): %d", addr, ret); ++ ++ return val; ++} ++ ++static u16 rtw_sdio_read16(struct rtw_dev *rtwdev, u32 addr) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ int ret; ++ u16 val; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ val = rtw_sdio_readw(rtwdev, addr, &ret); ++ else ++ val = rtw_sdio_indirect_read16(rtwdev, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio read16 failed (0x%x): %d", addr, ret); ++ ++ return val; ++} ++ ++static u32 rtw_sdio_read32(struct rtw_dev *rtwdev, u32 addr) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ u32 val; ++ int ret; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ val = rtw_sdio_readl(rtwdev, addr, &ret); ++ else ++ val = rtw_sdio_indirect_read32(rtwdev, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio read32 failed (0x%x): %d", addr, ret); ++ ++ return val; ++} ++ ++static void rtw_sdio_indirect_write8(struct rtw_dev *rtwdev, u8 val, u32 addr, ++ int *err_ret) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ u32 reg_data; ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ sdio_writeb(rtwsdio->sdio_func, val, reg_data, err_ret); ++ if (*err_ret) ++ return; ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_WRITE); ++} ++ ++static void rtw_sdio_indirect_write16(struct rtw_dev *rtwdev, u16 val, u32 addr, ++ int *err_ret) ++{ ++ u32 reg_data; ++ ++ if (!IS_ALIGNED(addr, 2)) { ++ addr = rtw_sdio_to_io_address(rtwdev, addr, true); ++ rtw_sdio_writew(rtwdev, val, addr, err_ret); ++ return; ++ } ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ rtw_sdio_writew(rtwdev, val, reg_data, err_ret); ++ if (*err_ret) ++ return; ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_WRITE | ++ BIT_SDIO_INDIRECT_REG_CFG_WORD); ++} ++ ++static void rtw_sdio_indirect_write32(struct rtw_dev *rtwdev, u32 val, ++ u32 addr, int *err_ret) ++{ ++ u32 reg_data; ++ ++ if (!IS_ALIGNED(addr, 4)) { ++ addr = rtw_sdio_to_io_address(rtwdev, addr, true); ++ rtw_sdio_writel(rtwdev, val, addr, err_ret); ++ return; ++ } ++ ++ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA); ++ rtw_sdio_writel(rtwdev, val, reg_data, err_ret); ++ ++ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr, ++ BIT_SDIO_INDIRECT_REG_CFG_WRITE | ++ BIT_SDIO_INDIRECT_REG_CFG_DWORD); ++} ++ ++static void rtw_sdio_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ int ret; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ sdio_writeb(rtwsdio->sdio_func, val, addr, &ret); ++ else ++ rtw_sdio_indirect_write8(rtwdev, val, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio write8 failed (0x%x): %d", addr, ret); ++} ++ ++static void rtw_sdio_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ int ret; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ rtw_sdio_writew(rtwdev, val, addr, &ret); ++ else ++ rtw_sdio_indirect_write16(rtwdev, val, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio write16 failed (0x%x): %d", addr, ret); ++} ++ ++static void rtw_sdio_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool direct, bus_claim; ++ int ret; ++ ++ direct = rtw_sdio_use_direct_io(rtwdev, addr); ++ addr = rtw_sdio_to_io_address(rtwdev, addr, direct); ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ if (direct) ++ rtw_sdio_writel(rtwdev, val, addr, &ret); ++ else ++ rtw_sdio_indirect_write32(rtwdev, val, addr, &ret); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, "sdio write32 failed (0x%x): %d", addr, ret); ++} ++ ++static u32 rtw_sdio_get_tx_addr(struct rtw_dev *rtwdev, size_t size, ++ enum rtw_tx_queue_type queue) ++{ ++ u32 txaddr; ++ ++ switch (queue) { ++ case RTW_TX_QUEUE_BCN: ++ case RTW_TX_QUEUE_H2C: ++ case RTW_TX_QUEUE_HI0: ++ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_TXFF_HIGH); ++ break; ++ case RTW_TX_QUEUE_VI: ++ case RTW_TX_QUEUE_VO: ++ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_TXFF_NORMAL); ++ break; ++ case RTW_TX_QUEUE_BE: ++ case RTW_TX_QUEUE_BK: ++ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_TXFF_LOW); ++ break; ++ case RTW_TX_QUEUE_MGMT: ++ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK, ++ REG_SDIO_CMD_ADDR_TXFF_EXTRA); ++ break; ++ default: ++ rtw_warn(rtwdev, "Unsupported queue for TX addr: 0x%02x\n", ++ queue); ++ return 0; ++ } ++ ++ txaddr += DIV_ROUND_UP(size, 4); ++ ++ return txaddr; ++}; ++ ++static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ struct mmc_host *host = rtwsdio->sdio_func->card->host; ++ bool bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ u32 rxaddr = rtwsdio->rx_addr++; ++ int ret = 0, err; ++ size_t bytes; ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ while (count > 0) { ++ bytes = min_t(size_t, host->max_req_size, count); ++ ++ err = sdio_memcpy_fromio(rtwsdio->sdio_func, buf, ++ RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), ++ bytes); ++ if (err) { ++ rtw_warn(rtwdev, ++ "Failed to read %zu byte(s) from SDIO port 0x%08x: %d", ++ bytes, rxaddr, err); ++ ++ /* Signal to the caller that reading did not work and ++ * that the data in the buffer is short/corrupted. ++ */ ++ ret = err; ++ ++ /* Don't stop here - instead drain the remaining data ++ * from the card's buffer, else the card will return ++ * corrupt data for the next rtw_sdio_read_port() call. ++ */ ++ } ++ ++ count -= bytes; ++ buf += bytes; ++ } ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ return ret; ++} ++ ++static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue, ++ size_t count) ++{ ++ unsigned int pages_free, pages_needed; ++ ++ if (rtw_chip_wcpu_11n(rtwdev)) { ++ u32 free_txpg; ++ ++ free_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG); ++ ++ switch (queue) { ++ case RTW_TX_QUEUE_BCN: ++ case RTW_TX_QUEUE_H2C: ++ case RTW_TX_QUEUE_HI0: ++ case RTW_TX_QUEUE_MGMT: ++ /* high */ ++ pages_free = free_txpg & 0xff; ++ break; ++ case RTW_TX_QUEUE_VI: ++ case RTW_TX_QUEUE_VO: ++ /* normal */ ++ pages_free = (free_txpg >> 8) & 0xff; ++ break; ++ case RTW_TX_QUEUE_BE: ++ case RTW_TX_QUEUE_BK: ++ /* low */ ++ pages_free = (free_txpg >> 16) & 0xff; ++ break; ++ default: ++ rtw_warn(rtwdev, "Unknown mapping for queue %u\n", queue); ++ return -EINVAL; ++ } ++ ++ /* add the pages from the public queue */ ++ pages_free += (free_txpg >> 24) & 0xff; ++ } else { ++ u32 free_txpg[3]; ++ ++ free_txpg[0] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG); ++ free_txpg[1] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG + 4); ++ free_txpg[2] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG + 8); ++ ++ switch (queue) { ++ case RTW_TX_QUEUE_BCN: ++ case RTW_TX_QUEUE_H2C: ++ case RTW_TX_QUEUE_HI0: ++ /* high */ ++ pages_free = free_txpg[0] & 0xfff; ++ break; ++ case RTW_TX_QUEUE_VI: ++ case RTW_TX_QUEUE_VO: ++ /* normal */ ++ pages_free = (free_txpg[0] >> 16) & 0xfff; ++ break; ++ case RTW_TX_QUEUE_BE: ++ case RTW_TX_QUEUE_BK: ++ /* low */ ++ pages_free = free_txpg[1] & 0xfff; ++ break; ++ case RTW_TX_QUEUE_MGMT: ++ /* extra */ ++ pages_free = free_txpg[2] & 0xfff; ++ break; ++ default: ++ rtw_warn(rtwdev, "Unknown mapping for queue %u\n", queue); ++ return -EINVAL; ++ } ++ ++ /* add the pages from the public queue */ ++ pages_free += (free_txpg[1] >> 16) & 0xfff; ++ } ++ ++ pages_needed = DIV_ROUND_UP(count, rtwdev->chip->page_size); ++ ++ if (pages_needed > pages_free) { ++ rtw_dbg(rtwdev, RTW_DBG_SDIO, ++ "Not enough free pages (%u needed, %u free) in queue %u for %zu bytes\n", ++ pages_needed, pages_free, queue, count); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb, ++ enum rtw_tx_queue_type queue) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool bus_claim; ++ size_t txsize; ++ u32 txaddr; ++ int ret; ++ ++ txaddr = rtw_sdio_get_tx_addr(rtwdev, skb->len, queue); ++ if (!txaddr) ++ return -EINVAL; ++ ++ txsize = sdio_align_size(rtwsdio->sdio_func, skb->len); ++ ++ ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize); ++ if (ret) ++ return ret; ++ ++ if (!IS_ALIGNED((unsigned long)skb->data, RTW_SDIO_DATA_PTR_ALIGN)) ++ rtw_warn(rtwdev, "Got unaligned SKB in %s() for queue %u\n", ++ __func__, queue); ++ ++ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); ++ ++ if (bus_claim) ++ sdio_claim_host(rtwsdio->sdio_func); ++ ++ ret = sdio_memcpy_toio(rtwsdio->sdio_func, txaddr, skb->data, txsize); ++ ++ if (bus_claim) ++ sdio_release_host(rtwsdio->sdio_func); ++ ++ if (ret) ++ rtw_warn(rtwdev, ++ "Failed to write %zu byte(s) to SDIO port 0x%08x", ++ txsize, txaddr); ++ ++ return ret; ++} ++ ++static void rtw_sdio_init(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ rtwsdio->irq_mask = REG_SDIO_HIMR_RX_REQUEST | REG_SDIO_HIMR_CPWM1; ++} ++ ++static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev) ++{ ++ u8 size, timeout; ++ ++ if (rtw_chip_wcpu_11n(rtwdev)) { ++ size = 0x6; ++ timeout = 0x6; ++ } else { ++ size = 0xff; ++ timeout = 0x1; ++ } ++ ++ /* Make the firmware honor the size limit configured below */ ++ rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC); ++ ++ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN); ++ ++ rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, ++ FIELD_PREP(BIT_RXDMA_AGG_PG_TH, size) | ++ FIELD_PREP(BIT_DMA_AGG_TO_V1, timeout)); ++ ++ rtw_write8_set(rtwdev, REG_RXDMA_MODE, BIT_DMA_MODE); ++} ++ ++static void rtw_sdio_enable_interrupt(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ rtw_write32(rtwdev, REG_SDIO_HIMR, rtwsdio->irq_mask); ++} ++ ++static void rtw_sdio_disable_interrupt(struct rtw_dev *rtwdev) ++{ ++ rtw_write32(rtwdev, REG_SDIO_HIMR, 0x0); ++} ++ ++static u8 rtw_sdio_get_tx_qsel(struct rtw_dev *rtwdev, struct sk_buff *skb, ++ u8 queue) ++{ ++ switch (queue) { ++ case RTW_TX_QUEUE_BCN: ++ return TX_DESC_QSEL_BEACON; ++ case RTW_TX_QUEUE_H2C: ++ return TX_DESC_QSEL_H2C; ++ case RTW_TX_QUEUE_MGMT: ++ if (rtw_chip_wcpu_11n(rtwdev)) ++ return TX_DESC_QSEL_HIGH; ++ else ++ return TX_DESC_QSEL_MGMT; ++ case RTW_TX_QUEUE_HI0: ++ return TX_DESC_QSEL_HIGH; ++ default: ++ return skb->priority; ++ } ++} ++ ++static int rtw_sdio_setup(struct rtw_dev *rtwdev) ++{ ++ /* nothing to do */ ++ return 0; ++} ++ ++static int rtw_sdio_start(struct rtw_dev *rtwdev) ++{ ++ rtw_sdio_enable_rx_aggregation(rtwdev); ++ rtw_sdio_enable_interrupt(rtwdev); ++ ++ return 0; ++} ++ ++static void rtw_sdio_stop(struct rtw_dev *rtwdev) ++{ ++ rtw_sdio_disable_interrupt(rtwdev); ++} ++ ++static void rtw_sdio_deep_ps_enter(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ bool tx_empty = true; ++ u8 queue; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) { ++ /* Deep PS state is not allowed to TX-DMA */ ++ for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) { ++ /* BCN queue is rsvd page, does not have DMA interrupt ++ * H2C queue is managed by firmware ++ */ ++ if (queue == RTW_TX_QUEUE_BCN || ++ queue == RTW_TX_QUEUE_H2C) ++ continue; ++ ++ /* check if there is any skb DMAing */ ++ if (skb_queue_len(&rtwsdio->tx_queue[queue])) { ++ tx_empty = false; ++ break; ++ } ++ } ++ } ++ ++ if (!tx_empty) { ++ rtw_dbg(rtwdev, RTW_DBG_PS, ++ "TX path not empty, cannot enter deep power save state\n"); ++ return; ++ } ++ ++ set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags); ++ rtw_power_mode_change(rtwdev, true); ++} ++ ++static void rtw_sdio_deep_ps_leave(struct rtw_dev *rtwdev) ++{ ++ if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) ++ rtw_power_mode_change(rtwdev, false); ++} ++ ++static void rtw_sdio_deep_ps(struct rtw_dev *rtwdev, bool enter) ++{ ++ if (enter && !test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) ++ rtw_sdio_deep_ps_enter(rtwdev); ++ ++ if (!enter && test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) ++ rtw_sdio_deep_ps_leave(rtwdev); ++} ++ ++static void rtw_sdio_tx_kick_off(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ queue_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work); ++} ++ ++static void rtw_sdio_link_ps(struct rtw_dev *rtwdev, bool enter) ++{ ++ /* nothing to do */ ++} ++ ++static void rtw_sdio_interface_cfg(struct rtw_dev *rtwdev) ++{ ++ u32 val; ++ ++ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG); ++ ++ val = rtw_read32(rtwdev, REG_SDIO_TX_CTRL); ++ val &= 0xfff8; ++ rtw_write32(rtwdev, REG_SDIO_TX_CTRL, val); ++} ++ ++static struct rtw_sdio_tx_data *rtw_sdio_get_tx_data(struct sk_buff *skb) ++{ ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ ++ BUILD_BUG_ON(sizeof(struct rtw_sdio_tx_data) > ++ sizeof(info->status.status_driver_data)); ++ ++ return (struct rtw_sdio_tx_data *)info->status.status_driver_data; ++} ++ ++static void rtw_sdio_tx_skb_prepare(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ struct sk_buff *skb, ++ enum rtw_tx_queue_type queue) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ unsigned long data_addr, aligned_addr; ++ size_t offset; ++ u8 *pkt_desc; ++ ++ pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); ++ ++ data_addr = (unsigned long)pkt_desc; ++ aligned_addr = ALIGN(data_addr, RTW_SDIO_DATA_PTR_ALIGN); ++ ++ if (data_addr != aligned_addr) { ++ /* Ensure that the start of the pkt_desc is always aligned at ++ * RTW_SDIO_DATA_PTR_ALIGN. ++ */ ++ offset = RTW_SDIO_DATA_PTR_ALIGN - (aligned_addr - data_addr); ++ ++ pkt_desc = skb_push(skb, offset); ++ ++ /* By inserting padding to align the start of the pkt_desc we ++ * need to inform the firmware that the actual data starts at ++ * a different offset than normal. ++ */ ++ pkt_info->offset += offset; ++ } ++ ++ memset(pkt_desc, 0, chip->tx_pkt_desc_sz); ++ ++ pkt_info->qsel = rtw_sdio_get_tx_qsel(rtwdev, skb, queue); ++ ++ rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, pkt_desc); ++} ++ ++static int rtw_sdio_write_data(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ struct sk_buff *skb, ++ enum rtw_tx_queue_type queue) ++{ ++ int ret; ++ ++ rtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue); ++ ++ ret = rtw_sdio_write_port(rtwdev, skb, queue); ++ dev_kfree_skb_any(skb); ++ ++ return ret; ++} ++ ++static int rtw_sdio_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, ++ u32 size) ++{ ++ struct rtw_tx_pkt_info pkt_info = {}; ++ struct sk_buff *skb; ++ ++ skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size); ++ if (!skb) ++ return -ENOMEM; ++ ++ return rtw_sdio_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); ++} ++ ++static int rtw_sdio_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) ++{ ++ struct rtw_tx_pkt_info pkt_info = {}; ++ struct sk_buff *skb; ++ ++ skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size); ++ if (!skb) ++ return -ENOMEM; ++ ++ return rtw_sdio_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); ++} ++ ++static int rtw_sdio_tx_write(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ struct sk_buff *skb) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb); ++ struct rtw_sdio_tx_data *tx_data; ++ ++ rtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue); ++ ++ tx_data = rtw_sdio_get_tx_data(skb); ++ tx_data->sn = pkt_info->sn; ++ ++ skb_queue_tail(&rtwsdio->tx_queue[queue], skb); ++ ++ return 0; ++} ++ ++static void rtw_sdio_tx_err_isr(struct rtw_dev *rtwdev) ++{ ++ u32 val = rtw_read32(rtwdev, REG_TXDMA_STATUS); ++ ++ rtw_write32(rtwdev, REG_TXDMA_STATUS, val); ++} ++ ++static void rtw_sdio_rx_skb(struct rtw_dev *rtwdev, struct sk_buff *skb, ++ u32 pkt_offset, struct rtw_rx_pkt_stat *pkt_stat, ++ struct ieee80211_rx_status *rx_status) ++{ ++ *IEEE80211_SKB_RXCB(skb) = *rx_status; ++ ++ if (pkt_stat->is_c2h) { ++ skb_put(skb, pkt_stat->pkt_len + pkt_offset); ++ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb); ++ return; ++ } ++ ++ skb_put(skb, pkt_stat->pkt_len); ++ skb_reserve(skb, pkt_offset); ++ ++ rtw_rx_stats(rtwdev, pkt_stat->vif, skb); ++ ++ ieee80211_rx_irqsafe(rtwdev->hw, skb); ++} ++ ++static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ u32 pkt_desc_sz = chip->rx_pkt_desc_sz; ++ struct ieee80211_rx_status rx_status; ++ struct rtw_rx_pkt_stat pkt_stat; ++ struct sk_buff *skb, *split_skb; ++ u32 pkt_offset, curr_pkt_len; ++ size_t bufsz; ++ u8 *rx_desc; ++ int ret; ++ ++ bufsz = sdio_align_size(rtwsdio->sdio_func, rx_len); ++ ++ skb = dev_alloc_skb(bufsz); ++ if (!skb) ++ return; ++ ++ ret = rtw_sdio_read_port(rtwdev, skb->data, bufsz); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ while (true) { ++ rx_desc = skb->data; ++ chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, ++ &rx_status); ++ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + ++ pkt_stat.shift; ++ ++ curr_pkt_len = ALIGN(pkt_offset + pkt_stat.pkt_len, ++ RTW_SDIO_DATA_PTR_ALIGN); ++ ++ if ((curr_pkt_len + pkt_desc_sz) >= rx_len) { ++ /* Use the original skb (with it's adjusted offset) ++ * when processing the last (or even the only) entry to ++ * have it's memory freed automatically. ++ */ ++ rtw_sdio_rx_skb(rtwdev, skb, pkt_offset, &pkt_stat, ++ &rx_status); ++ break; ++ } ++ ++ split_skb = dev_alloc_skb(curr_pkt_len); ++ if (!split_skb) { ++ rtw_sdio_rx_skb(rtwdev, skb, pkt_offset, &pkt_stat, ++ &rx_status); ++ break; ++ } ++ ++ skb_copy_header(split_skb, skb); ++ memcpy(split_skb->data, skb->data, curr_pkt_len); ++ ++ rtw_sdio_rx_skb(rtwdev, split_skb, pkt_offset, &pkt_stat, ++ &rx_status); ++ ++ /* Move to the start of the next RX descriptor */ ++ skb_reserve(skb, curr_pkt_len); ++ rx_len -= curr_pkt_len; ++ } ++} ++ ++static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) ++{ ++ u32 rx_len, hisr, total_rx_bytes = 0; ++ ++ do { ++ if (rtw_chip_wcpu_11n(rtwdev)) ++ rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN); ++ else ++ rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN); ++ ++ if (!rx_len) ++ break; ++ ++ rtw_sdio_rxfifo_recv(rtwdev, rx_len); ++ ++ total_rx_bytes += rx_len; ++ ++ if (rtw_chip_wcpu_11n(rtwdev)) { ++ /* Stop if no more RX requests are pending, even if ++ * rx_len could be greater than zero in the next ++ * iteration. This is needed because the RX buffer may ++ * already contain data while either HW or FW are not ++ * done filling that buffer yet. Still reading the ++ * buffer can result in packets where ++ * rtw_rx_pkt_stat.pkt_len is zero or points beyond the ++ * end of the buffer. ++ */ ++ hisr = rtw_read32(rtwdev, REG_SDIO_HISR); ++ } else { ++ /* RTW_WCPU_11AC chips have improved hardware or ++ * firmware and can use rx_len unconditionally. ++ */ ++ hisr = REG_SDIO_HISR_RX_REQUEST; ++ } ++ } while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST); ++} ++ ++static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func) ++{ ++ struct ieee80211_hw *hw = sdio_get_drvdata(sdio_func); ++ struct rtw_sdio *rtwsdio; ++ struct rtw_dev *rtwdev; ++ u32 hisr; ++ ++ rtwdev = hw->priv; ++ rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ rtwsdio->irq_thread = current; ++ ++ hisr = rtw_read32(rtwdev, REG_SDIO_HISR); ++ ++ if (hisr & REG_SDIO_HISR_TXERR) ++ rtw_sdio_tx_err_isr(rtwdev); ++ if (hisr & REG_SDIO_HISR_RX_REQUEST) { ++ hisr &= ~REG_SDIO_HISR_RX_REQUEST; ++ rtw_sdio_rx_isr(rtwdev); ++ } ++ ++ rtw_write32(rtwdev, REG_SDIO_HISR, hisr); ++ ++ rtwsdio->irq_thread = NULL; ++} ++ ++static int __maybe_unused rtw_sdio_suspend(struct device *dev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ struct ieee80211_hw *hw = dev_get_drvdata(dev); ++ struct rtw_dev *rtwdev = hw->priv; ++ int ret; ++ ++ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (ret) ++ rtw_err(rtwdev, "Failed to host PM flag MMC_PM_KEEP_POWER"); ++ ++ return ret; ++} ++ ++static int __maybe_unused rtw_sdio_resume(struct device *dev) ++{ ++ return 0; ++} ++ ++SIMPLE_DEV_PM_OPS(rtw_sdio_pm_ops, rtw_sdio_suspend, rtw_sdio_resume); ++EXPORT_SYMBOL(rtw_sdio_pm_ops); ++ ++static int rtw_sdio_claim(struct rtw_dev *rtwdev, struct sdio_func *sdio_func) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ int ret; ++ ++ sdio_claim_host(sdio_func); ++ ++ ret = sdio_enable_func(sdio_func); ++ if (ret) { ++ rtw_err(rtwdev, "Failed to enable SDIO func"); ++ goto err_release_host; ++ } ++ ++ ret = sdio_set_block_size(sdio_func, RTW_SDIO_BLOCK_SIZE); ++ if (ret) { ++ rtw_err(rtwdev, "Failed to set SDIO block size to 512"); ++ goto err_disable_func; ++ } ++ ++ rtwsdio->sdio_func = sdio_func; ++ ++ rtwsdio->sdio3_bus_mode = mmc_card_uhs(sdio_func->card); ++ ++ sdio_set_drvdata(sdio_func, rtwdev->hw); ++ SET_IEEE80211_DEV(rtwdev->hw, &sdio_func->dev); ++ ++ sdio_release_host(sdio_func); ++ ++ return 0; ++ ++err_disable_func: ++ sdio_disable_func(sdio_func); ++err_release_host: ++ sdio_release_host(sdio_func); ++ return ret; ++} ++ ++static void rtw_sdio_declaim(struct rtw_dev *rtwdev, ++ struct sdio_func *sdio_func) ++{ ++ sdio_claim_host(sdio_func); ++ sdio_disable_func(sdio_func); ++ sdio_release_host(sdio_func); ++} ++ ++static struct rtw_hci_ops rtw_sdio_ops = { ++ .tx_write = rtw_sdio_tx_write, ++ .tx_kick_off = rtw_sdio_tx_kick_off, ++ .setup = rtw_sdio_setup, ++ .start = rtw_sdio_start, ++ .stop = rtw_sdio_stop, ++ .deep_ps = rtw_sdio_deep_ps, ++ .link_ps = rtw_sdio_link_ps, ++ .interface_cfg = rtw_sdio_interface_cfg, ++ ++ .read8 = rtw_sdio_read8, ++ .read16 = rtw_sdio_read16, ++ .read32 = rtw_sdio_read32, ++ .write8 = rtw_sdio_write8, ++ .write16 = rtw_sdio_write16, ++ .write32 = rtw_sdio_write32, ++ .write_data_rsvd_page = rtw_sdio_write_data_rsvd_page, ++ .write_data_h2c = rtw_sdio_write_data_h2c, ++}; ++ ++static int rtw_sdio_request_irq(struct rtw_dev *rtwdev, ++ struct sdio_func *sdio_func) ++{ ++ int ret; ++ ++ sdio_claim_host(sdio_func); ++ ret = sdio_claim_irq(sdio_func, &rtw_sdio_handle_interrupt); ++ sdio_release_host(sdio_func); ++ ++ if (ret) { ++ rtw_err(rtwdev, "failed to claim SDIO IRQ"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void rtw_sdio_indicate_tx_status(struct rtw_dev *rtwdev, ++ struct sk_buff *skb) ++{ ++ struct rtw_sdio_tx_data *tx_data = rtw_sdio_get_tx_data(skb); ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hw *hw = rtwdev->hw; ++ ++ /* enqueue to wait for tx report */ ++ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { ++ rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn); ++ return; ++ } ++ ++ /* always ACK for others, then they won't be marked as drop */ ++ ieee80211_tx_info_clear_status(info); ++ if (info->flags & IEEE80211_TX_CTL_NO_ACK) ++ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ++ else ++ info->flags |= IEEE80211_TX_STAT_ACK; ++ ++ ieee80211_tx_status_irqsafe(hw, skb); ++} ++ ++static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev, ++ enum rtw_tx_queue_type queue) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ struct sk_buff *skb; ++ int ret; ++ ++ skb = skb_dequeue(&rtwsdio->tx_queue[queue]); ++ if (!skb) ++ return; ++ ++ ret = rtw_sdio_write_port(rtwdev, skb, queue); ++ if (ret) { ++ skb_queue_head(&rtwsdio->tx_queue[queue], skb); ++ return; ++ } ++ ++ if (queue <= RTW_TX_QUEUE_VO) ++ rtw_sdio_indicate_tx_status(rtwdev, skb); ++ else ++ dev_kfree_skb_any(skb); ++} ++ ++static void rtw_sdio_tx_handler(struct work_struct *work) ++{ ++ struct rtw_sdio_work_data *work_data = ++ container_of(work, struct rtw_sdio_work_data, work); ++ struct rtw_sdio *rtwsdio; ++ struct rtw_dev *rtwdev; ++ int limit, queue; ++ ++ rtwdev = work_data->rtwdev; ++ rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) ++ rtw_sdio_deep_ps_leave(rtwdev); ++ ++ for (queue = RTK_MAX_TX_QUEUE_NUM - 1; queue >= 0; queue--) { ++ for (limit = 0; limit < 1000; limit++) { ++ rtw_sdio_process_tx_queue(rtwdev, queue); ++ ++ if (skb_queue_empty(&rtwsdio->tx_queue[queue])) ++ break; ++ } ++ } ++} ++ ++static void rtw_sdio_free_irq(struct rtw_dev *rtwdev, ++ struct sdio_func *sdio_func) ++{ ++ sdio_claim_host(sdio_func); ++ sdio_release_irq(sdio_func); ++ sdio_release_host(sdio_func); ++} ++ ++static int rtw_sdio_init_tx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ int i; ++ ++ rtwsdio->txwq = create_singlethread_workqueue("rtw88_sdio: tx wq"); ++ if (!rtwsdio->txwq) { ++ rtw_err(rtwdev, "failed to create TX work queue\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) ++ skb_queue_head_init(&rtwsdio->tx_queue[i]); ++ rtwsdio->tx_handler_data = kmalloc(sizeof(*rtwsdio->tx_handler_data), ++ GFP_KERNEL); ++ if (!rtwsdio->tx_handler_data) ++ goto err_destroy_wq; ++ ++ rtwsdio->tx_handler_data->rtwdev = rtwdev; ++ INIT_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler); ++ ++ return 0; ++ ++err_destroy_wq: ++ destroy_workqueue(rtwsdio->txwq); ++ return -ENOMEM; ++} ++ ++static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ int i; ++ ++ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) ++ skb_queue_purge(&rtwsdio->tx_queue[i]); ++ ++ flush_workqueue(rtwsdio->txwq); ++ destroy_workqueue(rtwsdio->txwq); ++ kfree(rtwsdio->tx_handler_data); ++} ++ ++int rtw_sdio_probe(struct sdio_func *sdio_func, ++ const struct sdio_device_id *id) ++{ ++ struct ieee80211_hw *hw; ++ struct rtw_dev *rtwdev; ++ int drv_data_size; ++ int ret; ++ ++ drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_sdio); ++ hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops); ++ if (!hw) { ++ dev_err(&sdio_func->dev, "failed to allocate hw"); ++ return -ENOMEM; ++ } ++ ++ rtwdev = hw->priv; ++ rtwdev->hw = hw; ++ rtwdev->dev = &sdio_func->dev; ++ rtwdev->chip = (struct rtw_chip_info *)id->driver_data; ++ rtwdev->hci.ops = &rtw_sdio_ops; ++ rtwdev->hci.type = RTW_HCI_TYPE_SDIO; ++ ++ ret = rtw_core_init(rtwdev); ++ if (ret) ++ goto err_release_hw; ++ ++ rtw_dbg(rtwdev, RTW_DBG_SDIO, ++ "rtw88 SDIO probe: vendor=0x%04x device=%04x class=%02x", ++ id->vendor, id->device, id->class); ++ ++ ret = rtw_sdio_claim(rtwdev, sdio_func); ++ if (ret) { ++ rtw_err(rtwdev, "failed to claim SDIO device"); ++ goto err_deinit_core; ++ } ++ ++ rtw_sdio_init(rtwdev); ++ ++ ret = rtw_sdio_init_tx(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init SDIO TX queue\n"); ++ goto err_sdio_declaim; ++ } ++ ++ ret = rtw_chip_info_setup(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to setup chip information"); ++ goto err_destroy_txwq; ++ } ++ ++ ret = rtw_sdio_request_irq(rtwdev, sdio_func); ++ if (ret) ++ goto err_destroy_txwq; ++ ++ ret = rtw_register_hw(rtwdev, hw); ++ if (ret) { ++ rtw_err(rtwdev, "failed to register hw"); ++ goto err_free_irq; ++ } ++ ++ return 0; ++ ++err_free_irq: ++ rtw_sdio_free_irq(rtwdev, sdio_func); ++err_destroy_txwq: ++ rtw_sdio_deinit_tx(rtwdev); ++err_sdio_declaim: ++ rtw_sdio_declaim(rtwdev, sdio_func); ++err_deinit_core: ++ rtw_core_deinit(rtwdev); ++err_release_hw: ++ ieee80211_free_hw(hw); ++ ++ return ret; ++} ++EXPORT_SYMBOL(rtw_sdio_probe); ++ ++void rtw_sdio_remove(struct sdio_func *sdio_func) ++{ ++ struct ieee80211_hw *hw = sdio_get_drvdata(sdio_func); ++ struct rtw_dev *rtwdev; ++ ++ if (!hw) ++ return; ++ ++ rtwdev = hw->priv; ++ ++ rtw_unregister_hw(rtwdev, hw); ++ rtw_sdio_disable_interrupt(rtwdev); ++ rtw_sdio_free_irq(rtwdev, sdio_func); ++ rtw_sdio_declaim(rtwdev, sdio_func); ++ rtw_sdio_deinit_tx(rtwdev); ++ rtw_core_deinit(rtwdev); ++ ieee80211_free_hw(hw); ++} ++EXPORT_SYMBOL(rtw_sdio_remove); ++ ++void rtw_sdio_shutdown(struct device *dev) ++{ ++ struct sdio_func *sdio_func = dev_to_sdio_func(dev); ++ const struct rtw_chip_info *chip; ++ struct ieee80211_hw *hw; ++ struct rtw_dev *rtwdev; ++ ++ hw = sdio_get_drvdata(sdio_func); ++ if (!hw) ++ return; ++ ++ rtwdev = hw->priv; ++ chip = rtwdev->chip; ++ ++ if (chip->ops->shutdown) ++ chip->ops->shutdown(rtwdev); ++} ++EXPORT_SYMBOL(rtw_sdio_shutdown); ++ ++MODULE_AUTHOR("Martin Blumenstingl"); ++MODULE_AUTHOR("Jernej Skrabec"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless SDIO driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/sdio.h b/drivers/net/wireless/realtek/rtw88/sdio.h +new file mode 100644 +index 000000000000..3c659ed180f0 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sdio.h +@@ -0,0 +1,178 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright (C) 2021 Martin Blumenstingl ++ * Copyright (C) 2021 Jernej Skrabec ++ */ ++ ++#ifndef __REG_SDIO_H_ ++#define __REG_SDIO_H_ ++ ++/* I/O bus domain address mapping */ ++#define SDIO_LOCAL_OFFSET 0x10250000 ++#define WLAN_IOREG_OFFSET 0x10260000 ++#define FIRMWARE_FIFO_OFFSET 0x10270000 ++#define TX_HIQ_OFFSET 0x10310000 ++#define TX_MIQ_OFFSET 0x10320000 ++#define TX_LOQ_OFFSET 0x10330000 ++#define TX_EPQ_OFFSET 0x10350000 ++#define RX_RX0FF_OFFSET 0x10340000 ++ ++#define RTW_SDIO_BUS_MSK 0xffff0000 ++#define SDIO_LOCAL_REG_MSK 0x00000fff ++#define WLAN_IOREG_REG_MSK 0x0000ffff ++ ++/* SDIO Tx Control */ ++#define REG_SDIO_TX_CTRL (SDIO_LOCAL_OFFSET + 0x0000) ++ ++/*SDIO status timeout*/ ++#define REG_SDIO_TIMEOUT (SDIO_LOCAL_OFFSET + 0x0002) ++ ++/* SDIO Host Interrupt Mask */ ++#define REG_SDIO_HIMR (SDIO_LOCAL_OFFSET + 0x0014) ++#define REG_SDIO_HIMR_RX_REQUEST BIT(0) ++#define REG_SDIO_HIMR_AVAL BIT(1) ++#define REG_SDIO_HIMR_TXERR BIT(2) ++#define REG_SDIO_HIMR_RXERR BIT(3) ++#define REG_SDIO_HIMR_TXFOVW BIT(4) ++#define REG_SDIO_HIMR_RXFOVW BIT(5) ++#define REG_SDIO_HIMR_TXBCNOK BIT(6) ++#define REG_SDIO_HIMR_TXBCNERR BIT(7) ++#define REG_SDIO_HIMR_BCNERLY_INT BIT(16) ++#define REG_SDIO_HIMR_C2HCMD BIT(17) ++#define REG_SDIO_HIMR_CPWM1 BIT(18) ++#define REG_SDIO_HIMR_CPWM2 BIT(19) ++#define REG_SDIO_HIMR_HSISR_IND BIT(20) ++#define REG_SDIO_HIMR_GTINT3_IND BIT(21) ++#define REG_SDIO_HIMR_GTINT4_IND BIT(22) ++#define REG_SDIO_HIMR_PSTIMEOUT BIT(23) ++#define REG_SDIO_HIMR_OCPINT BIT(24) ++#define REG_SDIO_HIMR_ATIMEND BIT(25) ++#define REG_SDIO_HIMR_ATIMEND_E BIT(26) ++#define REG_SDIO_HIMR_CTWEND BIT(27) ++/* the following two are RTL8188 SDIO Specific */ ++#define REG_SDIO_HIMR_MCU_ERR BIT(28) ++#define REG_SDIO_HIMR_TSF_BIT32_TOGGLE BIT(29) ++ ++/* SDIO Host Interrupt Service Routine */ ++#define REG_SDIO_HISR (SDIO_LOCAL_OFFSET + 0x0018) ++#define REG_SDIO_HISR_RX_REQUEST BIT(0) ++#define REG_SDIO_HISR_AVAL BIT(1) ++#define REG_SDIO_HISR_TXERR BIT(2) ++#define REG_SDIO_HISR_RXERR BIT(3) ++#define REG_SDIO_HISR_TXFOVW BIT(4) ++#define REG_SDIO_HISR_RXFOVW BIT(5) ++#define REG_SDIO_HISR_TXBCNOK BIT(6) ++#define REG_SDIO_HISR_TXBCNERR BIT(7) ++#define REG_SDIO_HISR_BCNERLY_INT BIT(16) ++#define REG_SDIO_HISR_C2HCMD BIT(17) ++#define REG_SDIO_HISR_CPWM1 BIT(18) ++#define REG_SDIO_HISR_CPWM2 BIT(19) ++#define REG_SDIO_HISR_HSISR_IND BIT(20) ++#define REG_SDIO_HISR_GTINT3_IND BIT(21) ++#define REG_SDIO_HISR_GTINT4_IND BIT(22) ++#define REG_SDIO_HISR_PSTIMEOUT BIT(23) ++#define REG_SDIO_HISR_OCPINT BIT(24) ++#define REG_SDIO_HISR_ATIMEND BIT(25) ++#define REG_SDIO_HISR_ATIMEND_E BIT(26) ++#define REG_SDIO_HISR_CTWEND BIT(27) ++/* the following two are RTL8188 SDIO Specific */ ++#define REG_SDIO_HISR_MCU_ERR BIT(28) ++#define REG_SDIO_HISR_TSF_BIT32_TOGGLE BIT(29) ++ ++/* HCI Current Power Mode */ ++#define REG_SDIO_HCPWM (SDIO_LOCAL_OFFSET + 0x0019) ++/* RXDMA Request Length */ ++#define REG_SDIO_RX0_REQ_LEN (SDIO_LOCAL_OFFSET + 0x001C) ++/* OQT Free Page */ ++#define REG_SDIO_OQT_FREE_PG (SDIO_LOCAL_OFFSET + 0x001E) ++/* Free Tx Buffer Page */ ++#define REG_SDIO_FREE_TXPG (SDIO_LOCAL_OFFSET + 0x0020) ++/* HCI Current Power Mode 1 */ ++#define REG_SDIO_HCPWM1 (SDIO_LOCAL_OFFSET + 0x0024) ++/* HCI Current Power Mode 2 */ ++#define REG_SDIO_HCPWM2 (SDIO_LOCAL_OFFSET + 0x0026) ++/* Free Tx Page Sequence */ ++#define REG_SDIO_FREE_TXPG_SEQ (SDIO_LOCAL_OFFSET + 0x0028) ++/* HTSF Information */ ++#define REG_SDIO_HTSFR_INFO (SDIO_LOCAL_OFFSET + 0x0030) ++#define REG_SDIO_HCPWM1_V2 (SDIO_LOCAL_OFFSET + 0x0038) ++/* H2C */ ++#define REG_SDIO_H2C (SDIO_LOCAL_OFFSET + 0x0060) ++/* HCI Request Power Mode 1 */ ++#define REG_SDIO_HRPWM1 (SDIO_LOCAL_OFFSET + 0x0080) ++/* HCI Request Power Mode 2 */ ++#define REG_SDIO_HRPWM2 (SDIO_LOCAL_OFFSET + 0x0082) ++/* HCI Power Save Clock */ ++#define REG_SDIO_HPS_CLKR (SDIO_LOCAL_OFFSET + 0x0084) ++/* SDIO HCI Suspend Control */ ++#define REG_SDIO_HSUS_CTRL (SDIO_LOCAL_OFFSET + 0x0086) ++#define BIT_HCI_SUS_REQ BIT(0) ++#define BIT_HCI_RESUME_RDY BIT(1) ++/* SDIO Host Extension Interrupt Mask Always */ ++#define REG_SDIO_HIMR_ON (SDIO_LOCAL_OFFSET + 0x0090) ++/* SDIO Host Extension Interrupt Status Always */ ++#define REG_SDIO_HISR_ON (SDIO_LOCAL_OFFSET + 0x0091) ++ ++#define REG_SDIO_INDIRECT_REG_CFG (SDIO_LOCAL_OFFSET + 0x0040) ++#define BIT_SDIO_INDIRECT_REG_CFG_WORD BIT(16) ++#define BIT_SDIO_INDIRECT_REG_CFG_DWORD BIT(17) ++#define BIT_SDIO_INDIRECT_REG_CFG_WRITE BIT(18) ++#define BIT_SDIO_INDIRECT_REG_CFG_READ BIT(19) ++#define BIT_SDIO_INDIRECT_REG_CFG_UNK20 BIT(20) ++#define REG_SDIO_INDIRECT_REG_DATA (SDIO_LOCAL_OFFSET + 0x0044) ++ ++/* Sdio Address for SDIO Local Reg, TRX FIFO, MAC Reg */ ++#define REG_SDIO_CMD_ADDR_MSK GENMASK(16, 13) ++#define REG_SDIO_CMD_ADDR_SDIO_REG 0 ++#define REG_SDIO_CMD_ADDR_MAC_REG 8 ++#define REG_SDIO_CMD_ADDR_TXFF_HIGH 4 ++#define REG_SDIO_CMD_ADDR_TXFF_LOW 6 ++#define REG_SDIO_CMD_ADDR_TXFF_NORMAL 5 ++#define REG_SDIO_CMD_ADDR_TXFF_EXTRA 7 ++#define REG_SDIO_CMD_ADDR_RXFF 7 ++ ++#define RTW_SDIO_BLOCK_SIZE 512 ++#define RTW_SDIO_ADDR_RX_RX0FF_GEN(_id) (0x0e000 | ((_id) & 0x3)) ++ ++#define RTW_SDIO_DATA_PTR_ALIGN 8 ++ ++struct sdio_func; ++struct sdio_device_id; ++ ++struct rtw_sdio_tx_data { ++ u8 sn; ++}; ++ ++struct rtw_sdio_work_data { ++ struct work_struct work; ++ struct rtw_dev *rtwdev; ++}; ++ ++struct rtw_sdio { ++ struct sdio_func *sdio_func; ++ ++ u32 irq_mask; ++ u8 rx_addr; ++ bool sdio3_bus_mode; ++ ++ void *irq_thread; ++ ++ struct workqueue_struct *txwq; ++ struct rtw_sdio_work_data *tx_handler_data; ++ struct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM]; ++}; ++ ++extern const struct dev_pm_ops rtw_sdio_pm_ops; ++ ++int rtw_sdio_probe(struct sdio_func *sdio_func, ++ const struct sdio_device_id *id); ++void rtw_sdio_remove(struct sdio_func *sdio_func); ++void rtw_sdio_shutdown(struct device *dev); ++ ++static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev) ++{ ++ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; ++ ++ return rtwsdio->sdio3_bus_mode; ++} ++ ++#endif +diff --git a/drivers/net/wireless/realtek/rtw88/sdio_ids.h b/drivers/net/wireless/realtek/rtw88/sdio_ids.h +new file mode 100644 +index 000000000000..2d1a80776ac1 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/sdio_ids.h +@@ -0,0 +1,10 @@ ++#define SDIO_VENDOR_ID_REALTEK 0x024c ++#define SDIO_DEVICE_ID_REALTEK_RTW8723BS 0xb723 ++#define SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT 0xd723 ++#define SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT 0xd724 ++#define SDIO_DEVICE_ID_REALTEK_RTW8821BS 0xb821 ++#define SDIO_DEVICE_ID_REALTEK_RTW8821CS 0xc821 ++#define SDIO_DEVICE_ID_REALTEK_RTW8821DS 0xd821 ++#define SDIO_DEVICE_ID_REALTEK_RTW8822BS 0xb822 ++#define SDIO_DEVICE_ID_REALTEK_RTW8822CS 0xc822 ++ +diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c +index ca8072177ae3..77a8114b06d2 100644 +--- a/drivers/net/wireless/realtek/rtw88/tx.c ++++ b/drivers/net/wireless/realtek/rtw88/tx.c +@@ -34,41 +34,67 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + + void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) + { +- __le32 *txdesc = (__le32 *)skb->data; +- +- SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size); +- SET_TX_DESC_OFFSET(txdesc, pkt_info->offset); +- SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset); +- SET_TX_DESC_QSEL(txdesc, pkt_info->qsel); +- SET_TX_DESC_BMC(txdesc, pkt_info->bmc); +- SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id); +- SET_TX_DESC_DATARATE(txdesc, pkt_info->rate); +- SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback); +- SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate); +- SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type); +- SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw); +- SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq); +- SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor); +- SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density); +- SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc); +- SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc); +- SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en); +- SET_TX_DESC_LS(txdesc, pkt_info->ls); +- SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi); +- SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report); +- SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn); +- SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts); +- SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq); +- SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq); +- SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel); +- SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr); +- SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null); ++ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data; ++ bool more_data = false; ++ ++ if (pkt_info->qsel == TX_DESC_QSEL_HIGH) ++ more_data = true; ++ ++ tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) | ++ le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) | ++ le32_encode_bits(pkt_info->bmc, RTW_TX_DESC_W0_BMC) | ++ le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) | ++ le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ); ++ ++ tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) | ++ le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) | ++ le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) | ++ le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) | ++ le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA); ++ ++ tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) | ++ le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) | ++ le32_encode_bits(pkt_info->ampdu_density, RTW_TX_DESC_W2_AMPDU_DEN) | ++ le32_encode_bits(pkt_info->bt_null, RTW_TX_DESC_W2_BT_NULL); ++ ++ tx_desc->w3 = le32_encode_bits(pkt_info->hw_ssn_sel, RTW_TX_DESC_W3_HW_SSN_SEL) | ++ le32_encode_bits(pkt_info->use_rate, RTW_TX_DESC_W3_USE_RATE) | ++ le32_encode_bits(pkt_info->dis_rate_fallback, RTW_TX_DESC_W3_DISDATAFB) | ++ le32_encode_bits(pkt_info->rts, RTW_TX_DESC_W3_USE_RTS) | ++ le32_encode_bits(pkt_info->nav_use_hdr, RTW_TX_DESC_W3_NAVUSEHDR) | ++ le32_encode_bits(pkt_info->ampdu_factor, RTW_TX_DESC_W3_MAX_AGG_NUM); ++ ++ tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE); ++ ++ tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) | ++ le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) | ++ le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) | ++ le32_encode_bits(pkt_info->stbc, RTW_TX_DESC_W5_DATA_STBC); ++ ++ tx_desc->w6 = le32_encode_bits(pkt_info->sn, RTW_TX_DESC_W6_SW_DEFINE); ++ ++ tx_desc->w8 = le32_encode_bits(pkt_info->en_hwseq, RTW_TX_DESC_W8_EN_HWSEQ); ++ ++ tx_desc->w9 = le32_encode_bits(pkt_info->seq, RTW_TX_DESC_W9_SW_SEQ); ++ ++ if (pkt_info->rts) { ++ tx_desc->w4 |= le32_encode_bits(DESC_RATE24M, RTW_TX_DESC_W4_RTSRATE); ++ tx_desc->w5 |= le32_encode_bits(1, RTW_TX_DESC_W5_DATA_RTS_SHORT); ++ } ++ ++ if (pkt_info->tim_offset) ++ tx_desc->w9 |= le32_encode_bits(1, RTW_TX_DESC_W9_TIM_EN) | ++ le32_encode_bits(pkt_info->tim_offset, RTW_TX_DESC_W9_TIM_OFFSET); + } + EXPORT_SYMBOL(rtw_tx_fill_tx_desc); + + static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta) + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ u8 exp = sta->deflink.ht_cap.ampdu_factor; ++#else + u8 exp = sta->ht_cap.ampdu_factor; ++#endif + + /* the least ampdu factor is 8K, and the value in the tx desc is the + * max aggregation num, which represents val * 2 packets can be +@@ -79,7 +105,11 @@ static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta) + + static u8 get_tx_ampdu_density(struct ieee80211_sta *sta) + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ return sta->deflink.ht_cap.ampdu_density; ++#else + return sta->ht_cap.ampdu_density; ++#endif + } + + static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev, +@@ -87,7 +117,11 @@ static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev, + { + u8 rate; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (rtwdev->hal.rf_type == RF_2T2R && sta->deflink.ht_cap.mcs.rx_mask[1] != 0) ++#else + if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0) ++#endif + rate = DESC_RATEMCS15; + else + rate = DESC_RATEMCS7; +@@ -102,7 +136,11 @@ static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev, + u8 rate; + u16 tx_mcs_map; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map); ++#else + tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); ++#endif + if (efuse->hw_cap.nss == 1) { + switch (tx_mcs_map & 0x3) { + case IEEE80211_VHT_MCS_SUPPORT_0_7: +@@ -149,16 +187,24 @@ static void rtw_tx_report_enable(struct rtw_dev *rtwdev, + pkt_info->report = true; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + void rtw_tx_report_purge_timer(struct timer_list *t) ++#else ++void rtw_tx_report_purge_timer(void *cntx) ++#endif + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + struct rtw_dev *rtwdev = from_timer(rtwdev, t, tx_report.purge_timer); ++#else ++ struct rtw_dev *rtwdev = (struct rtw_dev *)cntx; ++#endif + struct rtw_tx_report *tx_report = &rtwdev->tx_report; + unsigned long flags; + + if (skb_queue_len(&tx_report->queue) == 0) + return; + +- WARN(1, "purge skb(s) not reported by firmware\n"); ++ rtw_warn(rtwdev, "failed to get tx report from firmware\n"); + + spin_lock_irqsave(&tx_report->q_lock, flags); + skb_queue_purge(&tx_report->queue); +@@ -229,17 +275,34 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src) + spin_unlock_irqrestore(&tx_report->q_lock, flags); + } + ++static u8 rtw_get_mgmt_rate(struct rtw_dev *rtwdev, struct sk_buff *skb, ++ u8 lowest_rate, bool ignore_rate) ++{ ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_vif *vif = tx_info->control.vif; ++ bool force_lowest = test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags); ++ ++ if (!vif || !vif->bss_conf.basic_rates || ignore_rate || force_lowest) ++ return lowest_rate; ++ ++ return __ffs(vif->bss_conf.basic_rates) + lowest_rate; ++} ++ + static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, +- struct sk_buff *skb) ++ struct sk_buff *skb, ++ bool ignore_rate) + { + if (rtwdev->hal.current_band_type == RTW_BAND_2G) { + pkt_info->rate_id = RTW_RATEID_B_20M; +- pkt_info->rate = DESC_RATE1M; ++ pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE1M, ++ ignore_rate); + } else { + pkt_info->rate_id = RTW_RATEID_G; +- pkt_info->rate = DESC_RATE6M; ++ pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE6M, ++ ignore_rate); + } ++ + pkt_info->use_rate = true; + pkt_info->dis_rate_fallback = true; + } +@@ -276,7 +339,7 @@ static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev, + struct ieee80211_sta *sta, + struct sk_buff *skb) + { +- rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb); ++ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, false); + pkt_info->dis_qselseq = true; + pkt_info->en_hwseq = true; + pkt_info->hw_ssn_sel = 0; +@@ -290,7 +353,10 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hw *hw = rtwdev->hw; ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_sta_info *si; ++ u8 fix_rate; + u16 seq; + u8 ampdu_factor = 0; + u8 ampdu_density = 0; +@@ -313,9 +379,19 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + ampdu_density = get_tx_ampdu_density(sta); + } + +- if (info->control.use_rts) ++ if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold) + pkt_info->rts = true; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++ if (sta->deflink.vht_cap.vht_supported) ++ rate = get_highest_vht_tx_rate(rtwdev, sta); ++ else if (sta->deflink.ht_cap.ht_supported) ++ rate = get_highest_ht_tx_rate(rtwdev, sta); ++ else if (sta->deflink.supp_rates[0] <= 0xf) ++ rate = DESC_RATE11M; ++ else ++ rate = DESC_RATE54M; ++#else + if (sta->vht_cap.vht_supported) + rate = get_highest_vht_tx_rate(rtwdev, sta); + else if (sta->ht_cap.ht_supported) +@@ -324,12 +400,13 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + rate = DESC_RATE11M; + else + rate = DESC_RATE54M; ++#endif + + si = (struct rtw_sta_info *)sta->drv_priv; + + bw = si->bw_mode; + rate_id = si->rate_id; +- stbc = si->stbc_en; ++ stbc = rtwdev->hal.txrx_1ss ? false : si->stbc_en; + ldpc = si->ldpc_en; + + out: +@@ -342,6 +419,13 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + pkt_info->bw = bw; + pkt_info->stbc = stbc; + pkt_info->ldpc = ldpc; ++ ++ fix_rate = dm_info->fix_rate; ++ if (fix_rate < DESC_RATE_MAX) { ++ pkt_info->rate = fix_rate; ++ pkt_info->dis_rate_fallback = true; ++ pkt_info->use_rate = true; ++ } + } + + void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, +@@ -349,7 +433,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, + struct ieee80211_sta *sta, + struct sk_buff *skb) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtw_sta_info *si; +@@ -389,7 +473,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, + struct sk_buff *skb, + enum rtw_rsvd_packet_type type) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool bmc; + +@@ -399,7 +483,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, + if (type != RSVD_BEACON && type != RSVD_DUMMY) + pkt_info->qsel = TX_DESC_QSEL_MGMT; + +- rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb); ++ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, true); + + bmc = is_broadcast_ether_addr(hdr->addr1) || + is_multicast_ether_addr(hdr->addr1); +@@ -417,6 +501,19 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, + if (type == RSVD_QOS_NULL) + pkt_info->bt_null = true; + ++ if (type == RSVD_BEACON) { ++ struct rtw_rsvd_page *rsvd_pkt; ++ int hdr_len; ++ ++ rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list, ++ struct rtw_rsvd_page, ++ build_list); ++ if (rsvd_pkt && rsvd_pkt->tim_offset != 0) { ++ hdr_len = sizeof(struct ieee80211_hdr_3addr); ++ pkt_info->tim_offset = rsvd_pkt->tim_offset - hdr_len; ++ } ++ } ++ + rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb); + + /* TODO: need to change hw port and hw ssn sel for multiple vifs */ +@@ -427,7 +524,7 @@ rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; + u32 tx_pkt_desc_sz; + u32 length; +@@ -453,7 +550,7 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; + u32 tx_pkt_desc_sz; + u32 length; +@@ -544,8 +641,6 @@ static int rtw_txq_push_skb(struct rtw_dev *rtwdev, + rtw_err(rtwdev, "failed to write TX skb to HCI\n"); + return ret; + } +- rtwtxq->last_push = jiffies; +- + return 0; + } + +@@ -587,9 +682,8 @@ static void rtw_txq_push(struct rtw_dev *rtwdev, + rcu_read_unlock(); + } + +-void rtw_tx_tasklet(struct tasklet_struct *t) ++void __rtw_tx_work(struct rtw_dev *rtwdev) + { +- struct rtw_dev *rtwdev = from_tasklet(rtwdev, t, tx_tasklet); + struct rtw_txq *rtwtxq, *tmp; + + spin_lock_bh(&rtwdev->txq_lock); +@@ -610,6 +704,13 @@ void rtw_tx_tasklet(struct tasklet_struct *t) + spin_unlock_bh(&rtwdev->txq_lock); + } + ++void rtw_tx_work(struct work_struct *w) ++{ ++ struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work); ++ ++ __rtw_tx_work(rtwdev); ++} ++ + void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq) + { + struct rtw_txq *rtwtxq; +@@ -634,3 +735,44 @@ void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq) + list_del_init(&rtwtxq->list); + spin_unlock_bh(&rtwdev->txq_lock); + } ++ ++static const enum rtw_tx_queue_type ac_to_hwq[] = { ++ [IEEE80211_AC_VO] = RTW_TX_QUEUE_VO, ++ [IEEE80211_AC_VI] = RTW_TX_QUEUE_VI, ++ [IEEE80211_AC_BE] = RTW_TX_QUEUE_BE, ++ [IEEE80211_AC_BK] = RTW_TX_QUEUE_BK, ++}; ++ ++static_assert(ARRAY_SIZE(ac_to_hwq) == IEEE80211_NUM_ACS); ++ ++enum rtw_tx_queue_type rtw_tx_ac_to_hwq(enum ieee80211_ac_numbers ac) ++{ ++ if (WARN_ON(unlikely(ac >= IEEE80211_NUM_ACS))) ++ return RTW_TX_QUEUE_BE; ++ ++ return ac_to_hwq[ac]; ++} ++EXPORT_SYMBOL(rtw_tx_ac_to_hwq); ++ ++enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ __le16 fc = hdr->frame_control; ++ u8 q_mapping = skb_get_queue_mapping(skb); ++ enum rtw_tx_queue_type queue; ++ ++ if (unlikely(ieee80211_is_beacon(fc))) ++ queue = RTW_TX_QUEUE_BCN; ++ else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) ++ queue = RTW_TX_QUEUE_MGMT; ++ else if (is_broadcast_ether_addr(hdr->addr1) || ++ is_multicast_ether_addr(hdr->addr1)) ++ queue = RTW_TX_QUEUE_HI0; ++ else if (WARN_ON_ONCE(q_mapping >= ARRAY_SIZE(ac_to_hwq))) ++ queue = ac_to_hwq[IEEE80211_AC_BE]; ++ else ++ queue = ac_to_hwq[q_mapping]; ++ ++ return queue; ++} ++EXPORT_SYMBOL(rtw_tx_queue_mapping); +diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h +index 6673dbcaa21c..324189606257 100644 +--- a/drivers/net/wireless/realtek/rtw88/tx.h ++++ b/drivers/net/wireless/realtek/rtw88/tx.h +@@ -9,60 +9,53 @@ + + #define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500) + +-#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0)) +-#define SET_TX_DESC_OFFSET(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16)) +-#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24)) +-#define SET_TX_DESC_QSEL(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8)) +-#define SET_TX_DESC_BMC(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24)) +-#define SET_TX_DESC_RATE_ID(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16)) +-#define SET_TX_DESC_DATARATE(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0)) +-#define SET_TX_DESC_DISDATAFB(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10)) +-#define SET_TX_DESC_USE_RATE(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8)) +-#define SET_TX_DESC_SEC_TYPE(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22)) +-#define SET_TX_DESC_DATA_BW(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5)) +-#define SET_TX_DESC_SW_SEQ(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12)) +-#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17)) +-#define SET_TX_DESC_USE_RTS(tx_desc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12)) +-#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20)) +-#define SET_TX_DESC_DATA_STBC(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8)) +-#define SET_TX_DESC_DATA_LDPC(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7)) +-#define SET_TX_DESC_AGG_EN(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12)) +-#define SET_TX_DESC_LS(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26)) +-#define SET_TX_DESC_DATA_SHORT(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4)) +-#define SET_TX_DESC_SPE_RPT(tx_desc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19)) +-#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0)) +-#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31)) +-#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15)) +-#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6)) +-#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15)) +-#define SET_TX_DESC_BT_NULL(txdesc, value) \ +- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23)) ++struct rtw_tx_desc { ++ __le32 w0; ++ __le32 w1; ++ __le32 w2; ++ __le32 w3; ++ __le32 w4; ++ __le32 w5; ++ __le32 w6; ++ __le32 w7; ++ __le32 w8; ++ __le32 w9; ++} __packed; ++ ++#define RTW_TX_DESC_W0_TXPKTSIZE GENMASK(15, 0) ++#define RTW_TX_DESC_W0_OFFSET GENMASK(23, 16) ++#define RTW_TX_DESC_W0_BMC BIT(24) ++#define RTW_TX_DESC_W0_LS BIT(26) ++#define RTW_TX_DESC_W0_DISQSELSEQ BIT(31) ++#define RTW_TX_DESC_W1_QSEL GENMASK(12, 8) ++#define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16) ++#define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22) ++#define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24) ++#define RTW_TX_DESC_W1_MORE_DATA BIT(29) ++#define RTW_TX_DESC_W2_AGG_EN BIT(12) ++#define RTW_TX_DESC_W2_SPE_RPT BIT(19) ++#define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20) ++#define RTW_TX_DESC_W2_BT_NULL BIT(23) ++#define RTW_TX_DESC_W3_HW_SSN_SEL GENMASK(7, 6) ++#define RTW_TX_DESC_W3_USE_RATE BIT(8) ++#define RTW_TX_DESC_W3_DISDATAFB BIT(10) ++#define RTW_TX_DESC_W3_USE_RTS BIT(12) ++#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15) ++#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17) ++#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0) ++#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24) ++#define RTW_TX_DESC_W5_DATA_SHORT BIT(4) ++#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5) ++#define RTW_TX_DESC_W5_DATA_LDPC BIT(7) ++#define RTW_TX_DESC_W5_DATA_STBC GENMASK(9, 8) ++#define RTW_TX_DESC_W5_DATA_RTS_SHORT BIT(12) ++#define RTW_TX_DESC_W6_SW_DEFINE GENMASK(11, 0) ++#define RTW_TX_DESC_W7_TXDESC_CHECKSUM GENMASK(15, 0) ++#define RTW_TX_DESC_W7_DMA_TXAGG_NUM GENMASK(31, 24) ++#define RTW_TX_DESC_W8_EN_HWSEQ BIT(15) ++#define RTW_TX_DESC_W9_SW_SEQ GENMASK(23, 12) ++#define RTW_TX_DESC_W9_TIM_EN BIT(7) ++#define RTW_TX_DESC_W9_TIM_OFFSET GENMASK(6, 0) + + enum rtw_tx_desc_queue_select { + TX_DESC_QSEL_TID0 = 0, +@@ -94,7 +87,8 @@ void rtw_tx(struct rtw_dev *rtwdev, + struct sk_buff *skb); + void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); + void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); +-void rtw_tx_tasklet(struct tasklet_struct *t); ++void rtw_tx_work(struct work_struct *w); ++void __rtw_tx_work(struct rtw_dev *rtwdev); + void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_sta *sta, +@@ -115,4 +109,32 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size); + ++enum rtw_tx_queue_type rtw_tx_ac_to_hwq(enum ieee80211_ac_numbers ac); ++enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb); ++ ++static inline ++void fill_txdesc_checksum_common(u8 *txdesc, size_t words) ++{ ++ __le16 chksum = 0; ++ __le16 *data = (__le16 *)(txdesc); ++ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc; ++ ++ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM); ++ ++ while (words--) ++ chksum ^= *data++; ++ ++ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum), ++ RTW_TX_DESC_W7_TXDESC_CHECKSUM); ++} ++ ++static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *txdesc) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ ++ chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc); ++} ++ + #endif +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +new file mode 100644 +index 000000000000..83efbb7b8a84 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -0,0 +1,956 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#include ++#include ++#include ++#include "main.h" ++#include "debug.h" ++#include "reg.h" ++#include "tx.h" ++#include "rx.h" ++#include "fw.h" ++#include "ps.h" ++#include "usb.h" ++ ++#define RTW_USB_MAX_RXQ_LEN 512 ++ ++struct rtw_usb_txcb { ++ struct rtw_dev *rtwdev; ++ struct sk_buff_head tx_ack_queue; ++}; ++ ++static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb, ++ struct sk_buff *skb, int agg_num) ++{ ++ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data; ++ struct rtw_dev *rtwdev = rtwusb->rtwdev; ++ struct rtw_tx_pkt_info pkt_info; ++ ++ le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM); ++ pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET); ++ rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data); ++} ++ ++static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct usb_device *udev = rtwusb->udev; ++ bool reg_on_section = false; ++ u16 t_reg = 0x4e0; ++ u8 t_len = 1; ++ int status; ++ ++ /* There are three sections: ++ * 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on ++ * 2. off (< 0xFE00, excluding "on" section): this section could be ++ * powered off ++ * 3. local (>= 0xFE00): usb specific registers section ++ */ ++ if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff)) ++ reg_on_section = true; ++ ++ if (!reg_on_section) ++ return; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, ++ t_reg, 0, data, t_len, 500); ++ ++ if (status != t_len && status != -ENODEV) ++ rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n", ++ __func__, t_reg, t_len, status); ++} ++ ++static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct usb_device *udev = rtwusb->udev; ++ __le32 *data; ++ unsigned long flags; ++ int idx, ret; ++ static int count; ++ ++ spin_lock_irqsave(&rtwusb->usb_lock, flags); ++ ++ idx = rtwusb->usb_data_index; ++ rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1); ++ ++ spin_unlock_irqrestore(&rtwusb->usb_lock, flags); ++ ++ data = &rtwusb->usb_data[idx]; ++ ++ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr, ++ RTW_USB_VENQT_CMD_IDX, data, len, 1000); ++ if (ret < 0 && ret != -ENODEV && count++ < 4) ++ rtw_err(rtwdev, "read register 0x%x failed with %d\n", ++ addr, ret); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8822B || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8821C) ++ rtw_usb_reg_sec(rtwdev, addr, data); ++ ++ return le32_to_cpu(*data); ++} ++ ++static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr) ++{ ++ return (u8)rtw_usb_read(rtwdev, addr, 1); ++} ++ ++static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr) ++{ ++ return (u16)rtw_usb_read(rtwdev, addr, 2); ++} ++ ++static u32 rtw_usb_read32(struct rtw_dev *rtwdev, u32 addr) ++{ ++ return (u32)rtw_usb_read(rtwdev, addr, 4); ++} ++ ++static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len) ++{ ++ struct rtw_usb *rtwusb = (struct rtw_usb *)rtwdev->priv; ++ struct usb_device *udev = rtwusb->udev; ++ unsigned long flags; ++ __le32 *data; ++ int idx, ret; ++ static int count; ++ ++ spin_lock_irqsave(&rtwusb->usb_lock, flags); ++ ++ idx = rtwusb->usb_data_index; ++ rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1); ++ ++ spin_unlock_irqrestore(&rtwusb->usb_lock, flags); ++ ++ data = &rtwusb->usb_data[idx]; ++ ++ *data = cpu_to_le32(val); ++ ++ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, ++ addr, 0, data, len, 30000); ++ if (ret < 0 && ret != -ENODEV && count++ < 4) ++ rtw_err(rtwdev, "write register 0x%x failed with %d\n", ++ addr, ret); ++ ++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8822B || ++ rtwdev->chip->id == RTW_CHIP_TYPE_8821C) ++ rtw_usb_reg_sec(rtwdev, addr, data); ++} ++ ++static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) ++{ ++ rtw_usb_write(rtwdev, addr, val, 1); ++} ++ ++static void rtw_usb_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) ++{ ++ rtw_usb_write(rtwdev, addr, val, 2); ++} ++ ++static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) ++{ ++ rtw_usb_write(rtwdev, addr, val, 4); ++} ++ ++static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping) ++{ ++ switch (dma_mapping) { ++ case RTW_DMA_MAPPING_HIGH: ++ return 0; ++ case RTW_DMA_MAPPING_NORMAL: ++ return 1; ++ case RTW_DMA_MAPPING_LOW: ++ return 2; ++ case RTW_DMA_MAPPING_EXTRA: ++ return 3; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int rtw_usb_parse(struct rtw_dev *rtwdev, ++ struct usb_interface *interface) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct usb_host_interface *host_interface = &interface->altsetting[0]; ++ struct usb_interface_descriptor *interface_desc = &host_interface->desc; ++ struct usb_endpoint_descriptor *endpoint; ++ int num_out_pipes = 0; ++ int i; ++ u8 num; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_rqpn *rqpn; ++ ++ for (i = 0; i < interface_desc->bNumEndpoints; i++) { ++ endpoint = &host_interface->endpoint[i].desc; ++ num = usb_endpoint_num(endpoint); ++ ++ if (usb_endpoint_dir_in(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (rtwusb->pipe_in) { ++ rtw_err(rtwdev, "IN pipes overflow\n"); ++ return -EINVAL; ++ } ++ ++ rtwusb->pipe_in = num; ++ } ++ ++ if (usb_endpoint_dir_in(endpoint) && ++ usb_endpoint_xfer_int(endpoint)) { ++ if (rtwusb->pipe_interrupt) { ++ rtw_err(rtwdev, "INT pipes overflow\n"); ++ return -EINVAL; ++ } ++ ++ rtwusb->pipe_interrupt = num; ++ } ++ ++ if (usb_endpoint_dir_out(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (num_out_pipes >= ARRAY_SIZE(rtwusb->out_ep)) { ++ rtw_err(rtwdev, "OUT pipes overflow\n"); ++ return -EINVAL; ++ } ++ ++ rtwusb->out_ep[num_out_pipes++] = num; ++ } ++ } ++ ++ rtwdev->hci.bulkout_num = num_out_pipes; ++ ++ if (num_out_pipes < 1 || num_out_pipes > 4) { ++ rtw_err(rtwdev, "invalid number of endpoints %d\n", num_out_pipes); ++ return -EINVAL; ++ } ++ ++ rqpn = &chip->rqpn_table[num_out_pipes]; ++ ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = dma_mapping_to_ep(rqpn->dma_map_be); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = dma_mapping_to_ep(rqpn->dma_map_bk); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = dma_mapping_to_ep(rqpn->dma_map_bk); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = dma_mapping_to_ep(rqpn->dma_map_be); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = dma_mapping_to_ep(rqpn->dma_map_vi); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = dma_mapping_to_ep(rqpn->dma_map_vi); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = dma_mapping_to_ep(rqpn->dma_map_vo); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = dma_mapping_to_ep(rqpn->dma_map_vo); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID8] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID9] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID10] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID11] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID12] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID13] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID14] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID15] = -EINVAL; ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_BEACON] = dma_mapping_to_ep(rqpn->dma_map_hi); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_HIGH] = dma_mapping_to_ep(rqpn->dma_map_hi); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_MGMT] = dma_mapping_to_ep(rqpn->dma_map_mg); ++ rtwusb->qsel_to_ep[TX_DESC_QSEL_H2C] = dma_mapping_to_ep(rqpn->dma_map_hi); ++ ++ return 0; ++} ++ ++static void rtw_usb_write_port_tx_complete(struct urb *urb) ++{ ++ struct rtw_usb_txcb *txcb = urb->context; ++ struct rtw_dev *rtwdev = txcb->rtwdev; ++ struct ieee80211_hw *hw = rtwdev->hw; ++ ++ while (true) { ++ struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue); ++ struct ieee80211_tx_info *info; ++ struct rtw_usb_tx_data *tx_data; ++ ++ if (!skb) ++ break; ++ ++ info = IEEE80211_SKB_CB(skb); ++ tx_data = rtw_usb_get_tx_data(skb); ++ ++ /* enqueue to wait for tx report */ ++ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { ++ rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn); ++ continue; ++ } ++ ++ /* always ACK for others, then they won't be marked as drop */ ++ ieee80211_tx_info_clear_status(info); ++ if (info->flags & IEEE80211_TX_CTL_NO_ACK) ++ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ++ else ++ info->flags |= IEEE80211_TX_STAT_ACK; ++ ++ ieee80211_tx_status_irqsafe(hw, skb); ++ } ++ ++ kfree(txcb); ++} ++ ++static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel) ++{ ++ if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep)) ++ return -EINVAL; ++ ++ return rtwusb->qsel_to_ep[qsel]; ++} ++ ++static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *skb, ++ usb_complete_t cb, void *context) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct usb_device *usbd = rtwusb->udev; ++ struct urb *urb; ++ unsigned int pipe; ++ int ret; ++ int ep = qsel_to_ep(rtwusb, qsel); ++ ++ if (ep < 0) ++ return ep; ++ ++ pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]); ++ urb = usb_alloc_urb(0, GFP_ATOMIC); ++ if (!urb) ++ return -ENOMEM; ++ ++ usb_fill_bulk_urb(urb, usbd, pipe, skb->data, skb->len, cb, context); ++ urb->transfer_flags |= URB_ZERO_PACKET; ++ ret = usb_submit_urb(urb, GFP_ATOMIC); ++ ++ usb_free_urb(urb); ++ ++ return ret; ++} ++ ++static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list) ++{ ++ struct rtw_dev *rtwdev = rtwusb->rtwdev; ++ struct rtw_tx_desc *tx_desc; ++ struct rtw_usb_txcb *txcb; ++ struct sk_buff *skb_head; ++ struct sk_buff *skb_iter; ++ int agg_num = 0; ++ unsigned int align_next = 0; ++ u8 qsel; ++ ++ if (skb_queue_empty(list)) ++ return false; ++ ++ txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC); ++ if (!txcb) ++ return false; ++ ++ txcb->rtwdev = rtwdev; ++ skb_queue_head_init(&txcb->tx_ack_queue); ++ ++ skb_iter = skb_dequeue(list); ++ ++ if (skb_queue_empty(list)) { ++ skb_head = skb_iter; ++ goto queue; ++ } ++ ++ skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ); ++ if (!skb_head) { ++ skb_head = skb_iter; ++ goto queue; ++ } ++ ++ while (skb_iter) { ++ unsigned long flags; ++ ++ skb_put(skb_head, align_next); ++ skb_put_data(skb_head, skb_iter->data, skb_iter->len); ++ ++ align_next = ALIGN(skb_iter->len, 8) - skb_iter->len; ++ ++ agg_num++; ++ ++ skb_queue_tail(&txcb->tx_ack_queue, skb_iter); ++ ++ spin_lock_irqsave(&list->lock, flags); ++ ++ skb_iter = skb_peek(list); ++ ++ if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ) ++ __skb_unlink(skb_iter, list); ++ else ++ skb_iter = NULL; ++ spin_unlock_irqrestore(&list->lock, flags); ++ } ++ ++ if (agg_num > 1) ++ rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num); ++ ++queue: ++ skb_queue_tail(&txcb->tx_ack_queue, skb_head); ++ tx_desc = (struct rtw_tx_desc *)skb_head->data; ++ qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL); ++ ++ rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb); ++ ++ return true; ++} ++ ++static void rtw_usb_tx_handler(struct work_struct *work) ++{ ++ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work); ++ int i, limit; ++ ++ for (i = ARRAY_SIZE(rtwusb->tx_queue) - 1; i >= 0; i--) { ++ for (limit = 0; limit < 200; limit++) { ++ struct sk_buff_head *list = &rtwusb->tx_queue[i]; ++ ++ if (!rtw_usb_tx_agg_skb(rtwusb, list)) ++ break; ++ } ++ } ++} ++ ++static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) ++ skb_queue_purge(&rtwusb->tx_queue[i]); ++} ++ ++static void rtw_usb_write_port_complete(struct urb *urb) ++{ ++ struct sk_buff *skb = urb->context; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static int rtw_usb_write_data(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ u8 *buf) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct sk_buff *skb; ++ unsigned int desclen, headsize, size; ++ u8 qsel; ++ int ret = 0; ++ ++ size = pkt_info->tx_pkt_size; ++ qsel = pkt_info->qsel; ++ desclen = chip->tx_pkt_desc_sz; ++ headsize = pkt_info->offset ? pkt_info->offset : desclen; ++ ++ skb = dev_alloc_skb(headsize + size); ++ if (unlikely(!skb)) ++ return -ENOMEM; ++ ++ skb_reserve(skb, headsize); ++ skb_put_data(skb, buf, size); ++ skb_push(skb, headsize); ++ memset(skb->data, 0, headsize); ++ rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); ++ ++ ret = rtw_usb_write_port(rtwdev, qsel, skb, ++ rtw_usb_write_port_complete, skb); ++ if (unlikely(ret)) ++ rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret); ++ ++ return ret; ++} ++ ++static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, ++ u32 size) ++{ ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_tx_pkt_info pkt_info = {0}; ++ ++ pkt_info.tx_pkt_size = size; ++ pkt_info.qsel = TX_DESC_QSEL_BEACON; ++ pkt_info.offset = chip->tx_pkt_desc_sz; ++ ++ return rtw_usb_write_data(rtwdev, &pkt_info, buf); ++} ++ ++static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) ++{ ++ struct rtw_tx_pkt_info pkt_info = {0}; ++ ++ pkt_info.tx_pkt_size = size; ++ pkt_info.qsel = TX_DESC_QSEL_H2C; ++ ++ return rtw_usb_write_data(rtwdev, &pkt_info, buf); ++} ++ ++static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ __le16 fc = hdr->frame_control; ++ u8 qsel; ++ ++ if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) ++ qsel = TX_DESC_QSEL_MGMT; ++ else if (is_broadcast_ether_addr(hdr->addr1) || ++ is_multicast_ether_addr(hdr->addr1)) ++ qsel = TX_DESC_QSEL_HIGH; ++ else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK) ++ qsel = skb->priority; ++ else ++ qsel = TX_DESC_QSEL_BEACON; ++ ++ return qsel; ++} ++ ++static int rtw_usb_tx_write(struct rtw_dev *rtwdev, ++ struct rtw_tx_pkt_info *pkt_info, ++ struct sk_buff *skb) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_usb_tx_data *tx_data; ++ u8 *pkt_desc; ++ int ep; ++ ++ pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(skb); ++ pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); ++ memset(pkt_desc, 0, chip->tx_pkt_desc_sz); ++ ep = qsel_to_ep(rtwusb, pkt_info->qsel); ++ rtw_tx_fill_tx_desc(pkt_info, skb); ++ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); ++ tx_data = rtw_usb_get_tx_data(skb); ++ tx_data->sn = pkt_info->sn; ++ ++ skb_queue_tail(&rtwusb->tx_queue[ep], skb); ++ ++ return 0; ++} ++ ++static void rtw_usb_tx_kick_off(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ ++ queue_work(rtwusb->txwq, &rtwusb->tx_work); ++} ++ ++static void rtw_usb_rx_handler(struct work_struct *work) ++{ ++ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work); ++ struct rtw_dev *rtwdev = rtwusb->rtwdev; ++ const struct rtw_chip_info *chip = rtwdev->chip; ++ struct rtw_rx_pkt_stat pkt_stat; ++ struct ieee80211_rx_status rx_status; ++ struct sk_buff *skb; ++ u32 pkt_desc_sz = chip->rx_pkt_desc_sz; ++ u32 pkt_offset; ++ u8 *rx_desc; ++ int limit; ++ ++ for (limit = 0; limit < 200; limit++) { ++ skb = skb_dequeue(&rtwusb->rx_queue); ++ if (!skb) ++ break; ++ ++ rx_desc = skb->data; ++ chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, ++ &rx_status); ++ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + ++ pkt_stat.shift; ++ ++ if (pkt_stat.is_c2h) { ++ skb_put(skb, pkt_stat.pkt_len + pkt_offset); ++ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb); ++ continue; ++ } ++ ++ if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) { ++ dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n"); ++ dev_kfree_skb_any(skb); ++ continue; ++ } ++ ++ skb_put(skb, pkt_stat.pkt_len); ++ skb_reserve(skb, pkt_offset); ++ memcpy(skb->cb, &rx_status, sizeof(rx_status)); ++ ieee80211_rx_irqsafe(rtwdev->hw, skb); ++ } ++} ++ ++static void rtw_usb_read_port_complete(struct urb *urb); ++ ++static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb) ++{ ++ struct rtw_dev *rtwdev = rtwusb->rtwdev; ++ int error; ++ ++ rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC); ++ if (!rxcb->rx_skb) ++ return; ++ ++ usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev, ++ usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in), ++ rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ, ++ rtw_usb_read_port_complete, rxcb); ++ ++ error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC); ++ if (error) { ++ kfree_skb(rxcb->rx_skb); ++ if (error != -ENODEV) ++ rtw_err(rtwdev, "Err sending rx data urb %d\n", ++ error); ++ } ++} ++ ++static void rtw_usb_read_port_complete(struct urb *urb) ++{ ++ struct rx_usb_ctrl_block *rxcb = urb->context; ++ struct rtw_dev *rtwdev = rxcb->rtwdev; ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct sk_buff *skb = rxcb->rx_skb; ++ ++ if (urb->status == 0) { ++ if (urb->actual_length >= RTW_USB_MAX_RECVBUF_SZ || ++ urb->actual_length < 24) { ++ rtw_err(rtwdev, "failed to get urb length:%d\n", ++ urb->actual_length); ++ if (skb) ++ dev_kfree_skb_any(skb); ++ } else { ++ skb_queue_tail(&rtwusb->rx_queue, skb); ++ queue_work(rtwusb->rxwq, &rtwusb->rx_work); ++ } ++ rtw_usb_rx_resubmit(rtwusb, rxcb); ++ } else { ++ switch (urb->status) { ++ case -EINVAL: ++ case -EPIPE: ++ case -ENODEV: ++ case -ESHUTDOWN: ++ case -ENOENT: ++ case -EPROTO: ++ case -EILSEQ: ++ case -ETIME: ++ case -ECOMM: ++ case -EOVERFLOW: ++ case -EINPROGRESS: ++ break; ++ default: ++ rtw_err(rtwdev, "status %d\n", urb->status); ++ break; ++ } ++ if (skb) ++ dev_kfree_skb_any(skb); ++ } ++} ++ ++static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb) ++{ ++ struct rx_usb_ctrl_block *rxcb; ++ int i; ++ ++ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { ++ rxcb = &rtwusb->rx_cb[i]; ++ if (rxcb->rx_urb) ++ usb_kill_urb(rxcb->rx_urb); ++ } ++} ++ ++static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb) ++{ ++ struct rx_usb_ctrl_block *rxcb; ++ int i; ++ ++ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { ++ rxcb = &rtwusb->rx_cb[i]; ++ if (rxcb->rx_urb) { ++ usb_kill_urb(rxcb->rx_urb); ++ usb_free_urb(rxcb->rx_urb); ++ } ++ } ++} ++ ++static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb) ++{ ++ int i; ++ ++ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { ++ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; ++ ++ rxcb->rtwdev = rtwusb->rtwdev; ++ rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!rxcb->rx_urb) ++ goto err; ++ } ++ ++ return 0; ++err: ++ rtw_usb_free_rx_bufs(rtwusb); ++ return -ENOMEM; ++} ++ ++static int rtw_usb_setup(struct rtw_dev *rtwdev) ++{ ++ /* empty function for rtw_hci_ops */ ++ return 0; ++} ++ ++static int rtw_usb_start(struct rtw_dev *rtwdev) ++{ ++ return 0; ++} ++ ++static void rtw_usb_stop(struct rtw_dev *rtwdev) ++{ ++} ++ ++static void rtw_usb_deep_ps(struct rtw_dev *rtwdev, bool enter) ++{ ++ /* empty function for rtw_hci_ops */ ++} ++ ++static void rtw_usb_link_ps(struct rtw_dev *rtwdev, bool enter) ++{ ++ /* empty function for rtw_hci_ops */ ++} ++ ++static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev) ++{ ++ /* empty function for rtw_hci_ops */ ++} ++ ++static struct rtw_hci_ops rtw_usb_ops = { ++ .tx_write = rtw_usb_tx_write, ++ .tx_kick_off = rtw_usb_tx_kick_off, ++ .setup = rtw_usb_setup, ++ .start = rtw_usb_start, ++ .stop = rtw_usb_stop, ++ .deep_ps = rtw_usb_deep_ps, ++ .link_ps = rtw_usb_link_ps, ++ .interface_cfg = rtw_usb_interface_cfg, ++ ++ .write8 = rtw_usb_write8, ++ .write16 = rtw_usb_write16, ++ .write32 = rtw_usb_write32, ++ .read8 = rtw_usb_read8, ++ .read16 = rtw_usb_read16, ++ .read32 = rtw_usb_read32, ++ ++ .write_data_rsvd_page = rtw_usb_write_data_rsvd_page, ++ .write_data_h2c = rtw_usb_write_data_h2c, ++}; ++ ++static int rtw_usb_init_rx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ int i; ++ ++ rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq"); ++ if (!rtwusb->rxwq) { ++ rtw_err(rtwdev, "failed to create RX work queue\n"); ++ return -ENOMEM; ++ } ++ ++ skb_queue_head_init(&rtwusb->rx_queue); ++ ++ INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler); ++ ++ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { ++ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; ++ ++ rtw_usb_rx_resubmit(rtwusb, rxcb); ++ } ++ ++ return 0; ++} ++ ++static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ ++ skb_queue_purge(&rtwusb->rx_queue); ++ ++ flush_workqueue(rtwusb->rxwq); ++ destroy_workqueue(rtwusb->rxwq); ++} ++ ++static int rtw_usb_init_tx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ int i; ++ ++ rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq"); ++ if (!rtwusb->txwq) { ++ rtw_err(rtwdev, "failed to create TX work queue\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) ++ skb_queue_head_init(&rtwusb->tx_queue[i]); ++ ++ INIT_WORK(&rtwusb->tx_work, rtw_usb_tx_handler); ++ ++ return 0; ++} ++ ++static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ ++ rtw_usb_tx_queue_purge(rtwusb); ++ flush_workqueue(rtwusb->txwq); ++ destroy_workqueue(rtwusb->txwq); ++} ++ ++static int rtw_usb_intf_init(struct rtw_dev *rtwdev, ++ struct usb_interface *intf) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf)); ++ int ret; ++ ++ rtwusb->udev = udev; ++ ret = rtw_usb_parse(rtwdev, intf); ++ if (ret) ++ return ret; ++ ++ rtwusb->usb_data = kcalloc(RTW_USB_MAX_RXTX_COUNT, sizeof(u32), ++ GFP_KERNEL); ++ if (!rtwusb->usb_data) ++ return -ENOMEM; ++ ++ usb_set_intfdata(intf, rtwdev->hw); ++ ++ SET_IEEE80211_DEV(rtwdev->hw, &intf->dev); ++ spin_lock_init(&rtwusb->usb_lock); ++ ++ return 0; ++} ++ ++static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev, ++ struct usb_interface *intf) ++{ ++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); ++ ++ usb_put_dev(rtwusb->udev); ++ kfree(rtwusb->usb_data); ++ usb_set_intfdata(intf, NULL); ++} ++ ++int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ++{ ++ struct rtw_dev *rtwdev; ++ struct ieee80211_hw *hw; ++ struct rtw_usb *rtwusb; ++ int drv_data_size; ++ int ret; ++ ++ drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_usb); ++ hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops); ++ if (!hw) ++ return -ENOMEM; ++ ++ rtwdev = hw->priv; ++ rtwdev->hw = hw; ++ rtwdev->dev = &intf->dev; ++ rtwdev->chip = (struct rtw_chip_info *)id->driver_info; ++ rtwdev->hci.ops = &rtw_usb_ops; ++ rtwdev->hci.type = RTW_HCI_TYPE_USB; ++ ++ rtwusb = rtw_get_usb_priv(rtwdev); ++ rtwusb->rtwdev = rtwdev; ++ ++ ret = rtw_usb_alloc_rx_bufs(rtwusb); ++ if (ret) ++ goto err_release_hw; ++ ++ ret = rtw_core_init(rtwdev); ++ if (ret) ++ goto err_free_rx_bufs; ++ ++ ret = rtw_usb_intf_init(rtwdev, intf); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init USB interface\n"); ++ goto err_deinit_core; ++ } ++ ++ ret = rtw_usb_init_tx(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init USB TX\n"); ++ goto err_destroy_usb; ++ } ++ ++ ret = rtw_usb_init_rx(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to init USB RX\n"); ++ goto err_destroy_txwq; ++ } ++ ++ ret = rtw_chip_info_setup(rtwdev); ++ if (ret) { ++ rtw_err(rtwdev, "failed to setup chip information\n"); ++ goto err_destroy_rxwq; ++ } ++ ++ ret = rtw_register_hw(rtwdev, rtwdev->hw); ++ if (ret) { ++ rtw_err(rtwdev, "failed to register hw\n"); ++ goto err_destroy_rxwq; ++ } ++ ++ return 0; ++ ++err_destroy_rxwq: ++ rtw_usb_deinit_rx(rtwdev); ++ ++err_destroy_txwq: ++ rtw_usb_deinit_tx(rtwdev); ++ ++err_destroy_usb: ++ rtw_usb_intf_deinit(rtwdev, intf); ++ ++err_deinit_core: ++ rtw_core_deinit(rtwdev); ++ ++err_free_rx_bufs: ++ rtw_usb_free_rx_bufs(rtwusb); ++ ++err_release_hw: ++ ieee80211_free_hw(hw); ++ ++ return ret; ++} ++EXPORT_SYMBOL(rtw_usb_probe); ++ ++void rtw_usb_disconnect(struct usb_interface *intf) ++{ ++ struct ieee80211_hw *hw = usb_get_intfdata(intf); ++ struct rtw_dev *rtwdev; ++ struct rtw_usb *rtwusb; ++ ++ if (!hw) ++ return; ++ ++ rtwdev = hw->priv; ++ rtwusb = rtw_get_usb_priv(rtwdev); ++ ++ rtw_usb_cancel_rx_bufs(rtwusb); ++ ++ rtw_unregister_hw(rtwdev, hw); ++ rtw_usb_deinit_tx(rtwdev); ++ rtw_usb_deinit_rx(rtwdev); ++ ++ if (rtwusb->udev->state != USB_STATE_NOTATTACHED) ++ usb_reset_device(rtwusb->udev); ++ ++ rtw_usb_free_rx_bufs(rtwusb); ++ ++ rtw_usb_intf_deinit(rtwdev, intf); ++ rtw_core_deinit(rtwdev); ++ ieee80211_free_hw(hw); ++} ++EXPORT_SYMBOL(rtw_usb_disconnect); ++ ++MODULE_AUTHOR("Realtek Corporation"); ++MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h +new file mode 100644 +index 000000000000..86697a5c0103 +--- /dev/null ++++ b/drivers/net/wireless/realtek/rtw88/usb.h +@@ -0,0 +1,100 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* Copyright(c) 2018-2019 Realtek Corporation ++ */ ++ ++#ifndef __RTW_USB_H_ ++#define __RTW_USB_H_ ++ ++#define FW_8192C_START_ADDRESS 0x1000 ++#define FW_8192C_END_ADDRESS 0x5fff ++ ++#define RTW_USB_MAX_RXTX_COUNT 128 ++#define RTW_USB_VENQT_MAX_BUF_SIZE 254 ++#define MAX_USBCTRL_VENDORREQ_TIMES 10 ++ ++#define RTW_USB_CMD_READ 0xc0 ++#define RTW_USB_CMD_WRITE 0x40 ++#define RTW_USB_CMD_REQ 0x05 ++ ++#define RTW_USB_VENQT_CMD_IDX 0x00 ++ ++#define RTW_USB_TX_SEL_HQ BIT(0) ++#define RTW_USB_TX_SEL_LQ BIT(1) ++#define RTW_USB_TX_SEL_NQ BIT(2) ++#define RTW_USB_TX_SEL_EQ BIT(3) ++ ++#define RTW_USB_BULK_IN_ADDR 0x80 ++#define RTW_USB_INT_IN_ADDR 0x81 ++ ++#define RTW_USB_HW_QUEUE_ENTRY 8 ++ ++#define RTW_USB_PACKET_OFFSET_SZ 8 ++#define RTW_USB_MAX_XMITBUF_SZ (1024 * 20) ++#define RTW_USB_MAX_RECVBUF_SZ 32768 ++ ++#define RTW_USB_RECVBUFF_ALIGN_SZ 8 ++ ++#define RTW_USB_RXAGG_SIZE 6 ++#define RTW_USB_RXAGG_TIMEOUT 10 ++ ++#define RTW_USB_RXCB_NUM 4 ++ ++#define RTW_USB_EP_MAX 4 ++ ++#define TX_DESC_QSEL_MAX 20 ++ ++#define RTW_USB_VENDOR_ID_REALTEK 0x0bda ++ ++static inline struct rtw_usb *rtw_get_usb_priv(struct rtw_dev *rtwdev) ++{ ++ return (struct rtw_usb *)rtwdev->priv; ++} ++ ++struct rx_usb_ctrl_block { ++ struct rtw_dev *rtwdev; ++ struct urb *rx_urb; ++ struct sk_buff *rx_skb; ++}; ++ ++struct rtw_usb_tx_data { ++ u8 sn; ++}; ++ ++struct rtw_usb { ++ struct rtw_dev *rtwdev; ++ struct usb_device *udev; ++ ++ /* protects usb_data_index */ ++ spinlock_t usb_lock; ++ __le32 *usb_data; ++ unsigned int usb_data_index; ++ ++ u8 pipe_interrupt; ++ u8 pipe_in; ++ u8 out_ep[RTW_USB_EP_MAX]; ++ int qsel_to_ep[TX_DESC_QSEL_MAX]; ++ ++ struct workqueue_struct *txwq, *rxwq; ++ ++ struct sk_buff_head tx_queue[RTW_USB_EP_MAX]; ++ struct work_struct tx_work; ++ ++ struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM]; ++ struct sk_buff_head rx_queue; ++ struct work_struct rx_work; ++}; ++ ++static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb) ++{ ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ ++ BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) > ++ sizeof(info->status.status_driver_data)); ++ ++ return (struct rtw_usb_tx_data *)info->status.status_driver_data; ++} ++ ++int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); ++void rtw_usb_disconnect(struct usb_interface *intf); ++ ++#endif +diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c +index 2c515af214e7..e222d3c01a77 100644 +--- a/drivers/net/wireless/realtek/rtw88/util.c ++++ b/drivers/net/wireless/realtek/rtw88/util.c +@@ -23,7 +23,7 @@ EXPORT_SYMBOL(check_hw_ready); + + bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) +@@ -37,7 +37,7 @@ bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val) + + bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value) + { +- struct rtw_chip_info *chip = rtwdev->chip; ++ const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) +@@ -105,3 +105,103 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) + *mcs = rate - DESC_RATEMCS0; + } + } ++ ++struct rtw_stas_entry { ++ struct list_head list; ++ struct ieee80211_sta *sta; ++}; ++ ++struct rtw_iter_stas_data { ++ struct rtw_dev *rtwdev; ++ struct list_head list; ++}; ++ ++static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw_iter_stas_data *iter_stas = data; ++ struct rtw_stas_entry *stas_entry; ++ ++ stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC); ++ if (!stas_entry) ++ return; ++ ++ stas_entry->sta = sta; ++ list_add_tail(&stas_entry->list, &iter_stas->list); ++} ++ ++void rtw_iterate_stas(struct rtw_dev *rtwdev, ++ void (*iterator)(void *data, ++ struct ieee80211_sta *sta), ++ void *data) ++{ ++ struct rtw_iter_stas_data iter_data; ++ struct rtw_stas_entry *sta_entry, *tmp; ++ ++ /* &rtwdev->mutex makes sure no stations can be removed between ++ * collecting the stations and iterating over them. ++ */ ++ lockdep_assert_held(&rtwdev->mutex); ++ ++ iter_data.rtwdev = rtwdev; ++ INIT_LIST_HEAD(&iter_data.list); ++ ++ ieee80211_iterate_stations_atomic(rtwdev->hw, rtw_collect_sta_iter, ++ &iter_data); ++ ++ list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, ++ list) { ++ list_del_init(&sta_entry->list); ++ iterator(data, sta_entry->sta); ++ kfree(sta_entry); ++ } ++} ++ ++struct rtw_vifs_entry { ++ struct list_head list; ++ struct ieee80211_vif *vif; ++}; ++ ++struct rtw_iter_vifs_data { ++ struct rtw_dev *rtwdev; ++ struct list_head list; ++}; ++ ++static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ++{ ++ struct rtw_iter_vifs_data *iter_stas = data; ++ struct rtw_vifs_entry *vifs_entry; ++ ++ vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC); ++ if (!vifs_entry) ++ return; ++ ++ vifs_entry->vif = vif; ++ list_add_tail(&vifs_entry->list, &iter_stas->list); ++} ++ ++void rtw_iterate_vifs(struct rtw_dev *rtwdev, ++ void (*iterator)(void *data, struct ieee80211_vif *vif), ++ void *data) ++{ ++ struct rtw_iter_vifs_data iter_data; ++ struct rtw_vifs_entry *vif_entry, *tmp; ++ ++ /* &rtwdev->mutex makes sure no interfaces can be removed between ++ * collecting the interfaces and iterating over them. ++ */ ++ lockdep_assert_held(&rtwdev->mutex); ++ ++ iter_data.rtwdev = rtwdev; ++ INIT_LIST_HEAD(&iter_data.list); ++ ++ ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, ++ IEEE80211_IFACE_ITER_NORMAL, ++ rtw_collect_vif_iter, &iter_data); ++ ++ list_for_each_entry_safe(vif_entry, tmp, &iter_data.list, ++ list) { ++ list_del_init(&vif_entry->list); ++ iterator(data, vif_entry->vif); ++ kfree(vif_entry); ++ } ++} +diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h +index 0c23b5069be0..f8399128a9a3 100644 +--- a/drivers/net/wireless/realtek/rtw88/util.h ++++ b/drivers/net/wireless/realtek/rtw88/util.h +@@ -7,9 +7,6 @@ + + struct rtw_dev; + +-#define rtw_iterate_vifs(rtwdev, iterator, data) \ +- ieee80211_iterate_active_interfaces(rtwdev->hw, \ +- IEEE80211_IFACE_ITER_NORMAL, iterator, data) + #define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \ + ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \ + IEEE80211_IFACE_ITER_NORMAL, iterator, data) +@@ -20,6 +17,14 @@ struct rtw_dev; + #define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \ + ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) + ++void rtw_iterate_vifs(struct rtw_dev *rtwdev, ++ void (*iterator)(void *data, struct ieee80211_vif *vif), ++ void *data); ++void rtw_iterate_stas(struct rtw_dev *rtwdev, ++ void (*iterator)(void *data, ++ struct ieee80211_sta *sta), ++ void *data); ++ + static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) + { + __le16 fc = hdr->frame_control; +diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c +index bb2fd4e544f0..16ddee577efe 100644 +--- a/drivers/net/wireless/realtek/rtw88/wow.c ++++ b/drivers/net/wireless/realtek/rtw88/wow.c +@@ -12,26 +12,54 @@ + + static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev) + { ++ struct cfg80211_wowlan_nd_info nd_info; ++ struct cfg80211_wowlan_wakeup wakeup = { ++ .pattern_idx = -1, ++ }; + u8 reason; + + reason = rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON); + +- if (reason == RTW_WOW_RSN_RX_DEAUTH) ++ switch (reason) { ++ case RTW_WOW_RSN_RX_DEAUTH: ++ wakeup.disconnect = true; + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx deauth\n"); +- else if (reason == RTW_WOW_RSN_DISCONNECT) ++ break; ++ case RTW_WOW_RSN_DISCONNECT: ++ wakeup.disconnect = true; + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: AP is off\n"); +- else if (reason == RTW_WOW_RSN_RX_MAGIC_PKT) ++ break; ++ case RTW_WOW_RSN_RX_MAGIC_PKT: ++ wakeup.magic_pkt = true; + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx magic packet\n"); +- else if (reason == RTW_WOW_RSN_RX_GTK_REKEY) ++ break; ++ case RTW_WOW_RSN_RX_GTK_REKEY: ++ wakeup.gtk_rekey_failure = true; + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n"); +- else if (reason == RTW_WOW_RSN_RX_PTK_REKEY) +- rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n"); +- else if (reason == RTW_WOW_RSN_RX_PATTERN_MATCH) ++ break; ++ case RTW_WOW_RSN_RX_PATTERN_MATCH: ++ /* Current firmware and driver don't report pattern index ++ * Use pattern_idx to 0 defaultly. ++ */ ++ wakeup.pattern_idx = 0; + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n"); +- else if (reason == RTW_WOW_RSN_RX_NLO) ++ break; ++ case RTW_WOW_RSN_RX_NLO: ++ /* Current firmware and driver don't report ssid index. ++ * Use 0 for n_matches based on its comment. ++ */ ++ nd_info.n_matches = 0; ++ wakeup.net_detect = &nd_info; + rtw_dbg(rtwdev, RTW_DBG_WOW, "Rx NLO\n"); +- else ++ break; ++ default: + rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason); ++ ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, ++ GFP_KERNEL); ++ return; ++ } ++ ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, ++ GFP_KERNEL); + } + + static void rtw_wow_pattern_write_cam(struct rtw_dev *rtwdev, u8 addr, +@@ -343,7 +371,8 @@ static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw, + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + default: +- rtw_err(rtwdev, "Unsupported key type for wowlan mode\n"); ++ rtw_err(rtwdev, "Unsupported key type for wowlan mode: %#x\n", ++ key->cipher); + hw_key_type = 0; + break; + } +@@ -442,37 +471,31 @@ static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect) + rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data); + } + +-static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev, +- struct rtw_vif *rtwvif) +-{ +- rtw_add_rsvd_page_pno(rtwdev, rtwvif); +-} +- +-static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev, +- struct rtw_vif *rtwvif) ++static int rtw_wow_config_wow_fw_rsvd_page(struct rtw_dev *rtwdev) + { +- rtw_add_rsvd_page_sta(rtwdev, rtwvif); +-} ++ struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; ++ struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; + +-static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev, +- struct rtw_vif *rtwvif) +-{ + rtw_remove_rsvd_page(rtwdev, rtwvif); + +- if (rtw_wow_mgd_linked(rtwdev)) { +- rtw_wow_config_linked_rsvd_page(rtwdev, rtwvif); +- } else if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags) && +- rtw_wow_no_link(rtwdev)) { +- rtw_wow_config_pno_rsvd_page(rtwdev, rtwvif); +- } ++ if (rtw_wow_no_link(rtwdev)) ++ rtw_add_rsvd_page_pno(rtwdev, rtwvif); ++ else ++ rtw_add_rsvd_page_sta(rtwdev, rtwvif); ++ ++ return rtw_fw_download_rsvd_page(rtwdev); + } + +-static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev) ++static int rtw_wow_config_normal_fw_rsvd_page(struct rtw_dev *rtwdev) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; + +- rtw_wow_config_rsvd_page(rtwdev, rtwvif); ++ rtw_remove_rsvd_page(rtwdev, rtwvif); ++ rtw_add_rsvd_page_sta(rtwdev, rtwvif); ++ ++ if (rtw_wow_no_link(rtwdev)) ++ return 0; + + return rtw_fw_download_rsvd_page(rtwdev); + } +@@ -566,10 +589,10 @@ static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev) + int ret = 0; + + if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) { +- if (rtw_fw_lps_deep_mode) ++ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE) + rtw_leave_lps_deep(rtwdev); + } else { +- if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) { ++ if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) { + rtw_wow->ips_enabled = true; + ret = rtw_leave_ips(rtwdev); + if (ret) +@@ -627,7 +650,8 @@ static int rtw_wow_enter_ps(struct rtw_dev *rtwdev) + + if (rtw_wow_mgd_linked(rtwdev)) + ret = rtw_wow_enter_linked_ps(rtwdev); +- else if (rtw_wow_no_link(rtwdev) && rtw_fw_lps_deep_mode) ++ else if (rtw_wow_no_link(rtwdev) && ++ rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE) + ret = rtw_wow_enter_no_link_ps(rtwdev); + + return ret; +@@ -669,7 +693,7 @@ static int rtw_wow_enable(struct rtw_dev *rtwdev) + + set_bit(RTW_FLAG_WOWLAN, rtwdev->flags); + +- ret = rtw_wow_dl_fw_rsvd_page(rtwdev); ++ ret = rtw_wow_config_wow_fw_rsvd_page(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to download wowlan rsvd page\n"); + goto error; +@@ -742,7 +766,7 @@ static int rtw_wow_disable(struct rtw_dev *rtwdev) + goto out; + } + +- ret = rtw_wow_dl_fw_rsvd_page(rtwdev); ++ ret = rtw_wow_config_normal_fw_rsvd_page(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to download normal rsvd page\n"); + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index c47512da9872..7af250c0ea68 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2924,6 +2924,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + quirks |= NVME_QUIRK_SIMPLE_SUSPEND; + } + ++#ifdef CONFIG_ARCH_PHYTIUM ++ if (read_cpuid_implementor() == ARM_CPU_IMP_PHYTIUM) ++ quirks |= NVME_QUIRK_SIMPLE_SUSPEND; ++#endif ++ + /* + * Double check that our mempool alloc size will cover the biggest + * command we support. +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index a4f09c46f040..09ea82a157ae 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -623,6 +623,18 @@ config SPI_PHYTIUM_QSPI + + If unsure, say N. + ++config SPI_PHYTIUM_V2 ++ tristate "spi phytium v2" ++ depends on ARCH_PHYTIUM || COMPILE_TEST ++ help ++ This config is similar to the "SPI_PHYTIUM" config. ++ ++config SPI_PHYTIUM_PLAT_V2 ++ tristate "Phytium SPI-V2 controller platform support" ++ select SPI_PHYTIUM_V2 ++ help ++ This config is similar to the "SPI_PHYTIUM_PLAT" config. ++ + config SPI_PIC32 + tristate "Microchip PIC32 series SPI" + depends on MACH_PIC32 || COMPILE_TEST +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 567bb2073106..94fe3555c3c7 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -86,7 +86,9 @@ obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium.o + obj-$(CONFIG_SPI_PHYTIUM_PLAT) += spi-phytium-plat.o + obj-$(CONFIG_SPI_PHYTIUM_PCI) += spi-phytium-pci.o + obj-$(CONFIG_SPI_PHYTIUM_QSPI) += spi-phytium-qspi.o +-obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium-dma.o ++obj-$(CONFIG_SPI_PHYTIUM_V2) += spi-phytium-common.o spi-phytium-v2.o ++obj-$(CONFIG_SPI_PHYTIUM_PLAT_V2) += spi-phytium-plat-v2.o ++obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium-dma.o + obj-$(CONFIG_SPI_PIC32) += spi-pic32.o + obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o + obj-$(CONFIG_SPI_PL022) += spi-pl022.o +diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c +new file mode 100644 +index 000000000000..0ccd92dc44d4 +--- /dev/null ++++ b/drivers/spi/spi-phytium-common.c +@@ -0,0 +1,454 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Phytium SPI core controller driver. ++ * ++ * Copyright (c) 2023-2024, Phytium Technology Co., Ltd.. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "spi-phytium.h" ++ ++#ifdef CONFIG_SHOW_MSG ++void spi_phytium_show_msg(struct msg *info) ++{ ++ pr_err("module:0x%4x, cmd:0x%04x, sub:0x%04x\n", ++ info->seq, info->cmd_id, info->cmd_subid); ++ ++ pr_err("0x%02x 0x%02x 0x%02x 0x%02x", info->data[0], ++ info->data[1], info->data[2], info->data[3]); ++ ++ pr_err("0x%02x 0x%02x 0x%02x 0x%02x", info->data[4], ++ info->data[5], info->data[6], info->data[7]); ++ ++ pr_err("0x%02x 0x%02x 0x%02x 0x%02x", info->data[8], ++ info->data[9], info->data[10], info->data[11]); ++ ++ pr_err("0x%02x 0x%02x 0x%02x 0x%02x", info->data[12], ++ info->data[13], info->data[14], info->data[15]); ++} ++#else ++void spi_phytium_show_msg(struct msg *info) { } ++#endif ++ ++void *memcpy_byte(void *_dest, const void *_src, size_t sz) ++{ ++ while (sz >= 8) { ++ *(u64 *)_dest = *(u64 *)_src; ++ _dest += 8; ++ _src += 8; ++ sz -= 8; ++ } ++ ++ while (sz) { ++ *(u8 *)_dest = *(u8 *)_src; ++ _dest++; ++ _src++; ++ sz--; ++ } ++ ++ return _dest; ++} ++ ++int spi_phytium_print_status(struct phytium_spi *fts, u8 status0, ++ u8 status1) ++{ ++ if (status1 == 0) ++ return 0; ++ ++ switch (status1) { ++ case 1: ++ pr_err("SPI Bus is busy.\n"); ++ break; ++ case 2: ++ pr_err("DMA queue transfer error.\n"); ++ break; ++ case 3: ++ pr_err("DMA transfer timeout.\n"); ++ break; ++ case 4: ++ pr_err("Operating flash timeout.\n"); ++ break; ++ case 5: ++ pr_err("spi_tx channel:DMA initialization failure.\n"); ++ break; ++ case 6: ++ pr_err("spi_rx channel:DMA initialization failure.\n"); ++ break; ++ case 7: ++ pr_err("DMA queue initialization failure.\n"); ++ break; ++ default: ++ pr_err("status=0x%x,Unknown error\n", status1); ++ break; ++ } ++ ++ return -1; ++} ++ ++int spi_phytium_check_result(struct phytium_spi *fts) ++{ ++ unsigned long long ms = 300000; ++ struct msg *msg = (struct msg *)fts->tx_shmem_addr; ++ ++ reinit_completion(&fts->cmd_completion); ++ ms = wait_for_completion_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); ++ ++ if (ms == 0) { ++ dev_err(&fts->master->dev, "SPI controller timed out\n"); ++ return -1; ++ } ++ ++ return spi_phytium_print_status(fts, msg->status0, msg->status1); ++} ++ ++int spi_phytium_set(struct phytium_spi *fts) ++{ ++ int ret; ++ ++ spi_phytium_show_msg(fts->msg); ++ phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ++ ret = spi_phytium_check_result(fts); ++ ++ return ret; ++} ++ ++void spi_phytium_default(struct phytium_spi *fts) ++{ ++ memset(fts->msg, 0, sizeof(struct msg)); ++ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_DEFAULT; ++ ++ spi_phytium_show_msg(fts->msg); ++ phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ++ spi_phytium_check_result(fts); ++} ++EXPORT_SYMBOL_GPL(spi_phytium_default); ++ ++void spi_phytium_set_subid(struct phytium_spi *fts, u16 sub_cmd) ++{ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_SET; ++ fts->msg->cmd_subid = sub_cmd; ++} ++ ++void spi_phytium_set_cmd8(struct phytium_spi *fts, u16 sub_cmd, ++ u8 data) ++{ ++ memset(fts->msg, 0, sizeof(struct msg)); ++ spi_phytium_set_subid(fts, sub_cmd); ++ fts->msg->data[0] = data; ++ spi_phytium_show_msg(fts->msg); ++ phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ++ spi_phytium_check_result(fts); ++} ++EXPORT_SYMBOL_GPL(spi_phytium_set_cmd8); ++ ++void spi_phytium_set_cmd16(struct phytium_spi *fts, u16 sub_cmd, ++ u16 data) ++{ ++ u16 *cp_data = (u16 *)&fts->msg->data[0]; ++ ++ memset(fts->msg, 0, sizeof(struct msg)); ++ spi_phytium_set_subid(fts, sub_cmd); ++ *cp_data = data; ++ spi_phytium_show_msg(fts->msg); ++ phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ++ spi_phytium_check_result(fts); ++} ++EXPORT_SYMBOL_GPL(spi_phytium_set_cmd16); ++ ++void spi_phytium_set_cmd32(struct phytium_spi *fts, u16 sub_cmd, ++ u32 data) ++{ ++ u32 *cp_data = (u32 *)&fts->msg->data[0]; ++ ++ memset(fts->msg, 0, sizeof(struct msg)); ++ spi_phytium_set_subid(fts, sub_cmd); ++ *cp_data = data; ++ spi_phytium_show_msg(fts->msg); ++ phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ++ spi_phytium_check_result(fts); ++} ++EXPORT_SYMBOL_GPL(spi_phytium_set_cmd32); ++ ++void spi_phytium_data_subid(struct phytium_spi *fts, u16 sub_cmd) ++{ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_DATA; ++ fts->msg->cmd_subid = sub_cmd; ++} ++ ++void spi_phytium_write_pre(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, u8 tmode, ++ u8 flags, u8 spi_write_flag) ++{ ++ struct msg *msg; ++ u32 len; ++ u64 smem_tx; ++ u8 first = 1; ++ u64 tx_addr; ++ ++ len = min((u32)(fts->tx_end - fts->tx), (u32)SPI_TRANS_DATA_SIZE); ++ msg = (struct msg *)((u64)fts->msg + (sizeof(struct msg) + FLASH_PAGE_SIZE)*spi_write_flag); ++ memset(msg, 0, sizeof(struct msg)); ++ ++ msg->cmd_id = PHYTSPI_MSG_CMD_DATA; ++ if (spi_write_flag) { ++ if (len > 16 && fts->dma_get_ddrdata) ++ msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_FLASH_DMA_TX; ++ else ++ msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_FLASH_TX; ++ } else { ++ if (len > 16 && fts->dma_get_ddrdata) ++ msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_DMA_TX; ++ else ++ msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_TX; ++ } ++ ++ if (len > 16 && fts->dma_get_ddrdata) { ++ tx_addr = (u64)__virt_to_phys((u64)fts->tx); ++ if (!tx_addr) { ++ dev_err(&fts->master->dev, "tx address translation failed\n"); ++ return; ++ } ++ *(u64 *)&msg->data[0] = tx_addr; ++ } else { ++ smem_tx = (u64)msg + sizeof(struct msg); ++ memcpy((void *)smem_tx, fts->tx, len); ++ *(u64 *)&msg->data[0] = sizeof(struct msg); ++ } ++ ++ *(u32 *)&msg->data[8] = len; ++ fts->tx += len; ++ msg->data[12] = cs; ++ msg->data[13] = dfs; ++ msg->data[14] = mode; ++ msg->data[15] = tmode; ++ msg->data[16] = flags; ++ msg->data[17] = first; ++ first = 0; ++} ++EXPORT_SYMBOL_GPL(spi_phytium_write_pre); ++ ++int spi_phytium_flash_erase(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags, u8 cmd) ++{ ++ u32 len; ++ u64 smem_tx; ++ u8 first = 1; ++ u8 cmd_addr[8]; ++ int ret; ++ ++ len = (u32)(fts->tx_end - fts->tx); ++ ++ memset(fts->msg, 0, sizeof(struct msg)); ++ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_DATA; ++ ++ if (cmd == SPINOR_OP_BE_4K || cmd == SPINOR_OP_CHIP_ERASE) ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_FLASH_ERASE; ++ else if (cmd == SPINOR_OP_READ || cmd == SPINOR_OP_READ_FAST || ++ cmd == SPINOR_OP_READ_4B || cmd == SPINOR_OP_READ_FAST_4B) ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_TX; ++ ++ smem_tx = (u64)fts->msg + sizeof(struct msg); ++ ++ cmd_addr[0] = cmd; ++ if (cmd == SPINOR_OP_BE_4K || cmd == SPINOR_OP_READ || ++ cmd == SPINOR_OP_READ_FAST || cmd == SPINOR_OP_READ_4B || ++ cmd == SPINOR_OP_READ_FAST_4B) { ++ memcpy_byte((void *)&cmd_addr[1], fts->tx, len); ++ memcpy_byte((void *)smem_tx, (void *)&cmd_addr[0], len + 1); ++ *(u32 *)&fts->msg->data[8] = len + 1; ++ } else if (cmd == SPINOR_OP_CHIP_ERASE) { ++ memcpy_byte((void *)smem_tx, (void *)&cmd_addr[0], 1); ++ *(u32 *)&fts->msg->data[8] = len; ++ } ++ ++ *(u32 *)&fts->msg->data[0] = sizeof(struct msg); ++ fts->tx += len; ++ fts->msg->data[12] = cs; ++ fts->msg->data[13] = dfs; ++ fts->msg->data[14] = mode; ++ fts->msg->data[15] = tmode; ++ fts->msg->data[16] = flags; ++ fts->msg->data[17] = first; ++ ++ ret = spi_phytium_set(fts); ++ if (ret) { ++ dev_err(&fts->master->dev, "AP <-> RV interaction failed\n"); ++ return ret; ++ } ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_phytium_flash_erase); ++ ++int spi_phytium_flash_write(struct phytium_spi *fts, u8 cmd) ++{ ++ u8 cmd_addr[8] = {0}; ++ ++ cmd_addr[0] = fts->len + 1; ++ cmd_addr[1] = cmd; ++ memcpy_byte((void *)&cmd_addr[2], fts->tx, fts->len); ++ ++ fts->msg->data[18] = cmd_addr[0]; ++ fts->msg->data[19] = cmd_addr[1]; ++ fts->msg->data[20] = cmd_addr[2]; ++ fts->msg->data[21] = cmd_addr[3]; ++ fts->msg->data[22] = cmd_addr[4]; ++ fts->msg->data[23] = cmd_addr[5]; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(spi_phytium_flash_write); ++ ++int spi_phytium_write(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags, u8 spi_write_flag) ++{ ++ int ret = 0; ++ u32 len; ++ u64 smem_tx; ++ u8 first = 1; ++ u64 tx_addr; ++ ++ if (spi_write_flag == 1) { ++ spi_phytium_set(fts); ++ if (ret) { ++ dev_err(&fts->master->dev, "AP <-> RV interaction failed\n"); ++ return ret; ++ } ++ } ++ ++ do { ++ len = min_t(u32, (u32)(fts->tx_end - fts->tx), ++ (u32)SPI_TRANS_DATA_SIZE); ++ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_DATA; ++ ++ if (spi_write_flag == 2) { ++ if (len > 16 && fts->dma_get_ddrdata) ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_FLASH_DMA_TX; ++ else ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_FLASH_TX; ++ } else { ++ if (len > 16 && fts->dma_get_ddrdata) ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_DMA_TX; ++ else ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_TX; ++ } ++ ++ if (len > 16 && fts->dma_get_ddrdata) { ++ tx_addr = __virt_to_phys((u64)fts->tx); ++ if (!tx_addr) { ++ dev_err(&fts->master->dev, "tx address translation failed\n"); ++ return -1; ++ } ++ *(u64 *)&fts->msg->data[0] = tx_addr; ++ } else { ++ smem_tx = (u64)fts->msg + sizeof(struct msg); ++ memcpy_byte((void *)smem_tx, fts->tx, len); ++ *(u64 *)&fts->msg->data[0] = sizeof(struct msg); ++ } ++ ++ *(u32 *)&fts->msg->data[8] = len; ++ fts->tx += len; ++ fts->msg->data[12] = cs; ++ fts->msg->data[13] = dfs; ++ fts->msg->data[14] = mode; ++ fts->msg->data[15] = tmode; ++ fts->msg->data[16] = flags; ++ fts->msg->data[17] = first; ++ ret = spi_phytium_set(fts); ++ if (ret) { ++ dev_err(&fts->master->dev, "AP <-> RV interaction failed\n"); ++ return ret; ++ } ++ ++ first = 0; ++ } while (fts->tx_end > fts->tx); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_phytium_write); ++ ++int spi_phytium_read(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags) ++{ ++ int ret; ++ u32 len; ++ u64 smem_rx; ++ u8 first = 1; ++ u64 rx_addr; ++ ++ do { ++ if (fts->dma_get_ddrdata) ++ len = min_t(u32, (u32)(fts->rx_end - fts->rx), ++ (u32)(fts->rx_end - fts->rx)); ++ else ++ len = min_t(u32, (u32)(fts->rx_end - fts->rx), 128); ++ ++ fts->msg->cmd_id = PHYTSPI_MSG_CMD_DATA; ++ ++ smem_rx = (u64)fts->msg + sizeof(struct msg); ++ ++ if (len > 16 && fts->dma_get_ddrdata) { ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_DMA_RX; ++ rx_addr = __virt_to_phys((u64)fts->rx); ++ if (!rx_addr) { ++ dev_err(&fts->master->dev, "rx address translation failed\n"); ++ return -1; ++ } ++ *(u64 *)&fts->msg->data[0] = rx_addr; ++ } else { ++ fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_RX; ++ *(u64 *)&fts->msg->data[0] = sizeof(struct msg); ++ } ++ ++ *(u32 *)&fts->msg->data[8] = len; ++ fts->msg->data[12] = cs; ++ fts->msg->data[13] = dfs; ++ fts->msg->data[14] = mode; ++ fts->msg->data[15] = tmode; ++ if (fts->rx_end <= fts->rx + len) ++ fts->msg->data[16] = flags; ++ else if (first == 1) ++ fts->msg->data[16] = 1; ++ else ++ fts->msg->data[16] = 0; ++ fts->msg->data[17] = first; ++ ret = spi_phytium_set(fts); ++ if (ret) { ++ dev_err(&fts->master->dev, "AP <-> RV interaction failed\n"); ++ return ret; ++ } ++ if (len <= 16 || !fts->dma_get_ddrdata) ++ memcpy_byte(fts->rx, (void *)smem_rx, len); ++ ++ fts->rx += len; ++ first = 0; ++ } while (fts->rx_end > fts->rx); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_phytium_read); ++ ++MODULE_AUTHOR("Peng Min "); ++MODULE_DESCRIPTION("Phytium SPI adapter core"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/spi/spi-phytium-pci.c b/drivers/spi/spi-phytium-pci.c +index 5bc68634277f..e1ff69916852 100644 +--- a/drivers/spi/spi-phytium-pci.c ++++ b/drivers/spi/spi-phytium-pci.c +@@ -23,6 +23,7 @@ + #include "spi-phytium.h" + + #define DRIVER_NAME "phytium_spi_pci" ++#define DRIVER_VERSION "1.0.0" + + static int phytium_spi_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +@@ -104,6 +105,7 @@ static const struct pci_device_id phytium_device_pci_tbl[] = { + { PCI_VDEVICE(PHYTIUM, 0xdc2c) }, + {}, + }; ++MODULE_DEVICE_TABLE(pci, phytium_device_pci_tbl); + + static struct pci_driver phytium_spi_pci_driver = { + .name = DRIVER_NAME, +@@ -120,3 +122,4 @@ module_pci_driver(phytium_spi_pci_driver); + MODULE_AUTHOR("Yiqun Zhang "); + MODULE_DESCRIPTION("PCI Driver for Phytium SPI controller core"); + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c +new file mode 100644 +index 000000000000..73fc2e5f09a9 +--- /dev/null ++++ b/drivers/spi/spi-phytium-plat-v2.c +@@ -0,0 +1,326 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Phytium SPI core controller platform driver. ++ * ++ * Copyright (c) 2023-2024, Phytium Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "spi-phytium.h" ++ ++#define DRIVER_NAME_PHYT "phytium_spi_2.0" ++#define DRIVER_VERSION "1.0.6" ++ ++#define PHYTIUM_CPU_PART_FTC872 0x872 ++ ++#define MIDR_PHYTIUM_FTC872 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC872) ++ ++static ssize_t debug_show(struct device *dev, ++ struct device_attribute *da, ++ char *buf) ++{ ++ struct phytium_spi *fts = dev_get_drvdata(dev); ++ ssize_t ret; ++ u32 reg; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ ret = sprintf(buf, "%x\n", reg); ++ ++ return ret; ++} ++ ++static ssize_t debug_store(struct device *dev, ++ struct device_attribute *da, const char *buf, ++ size_t size) ++{ ++ u8 loc, dis_en, status = 0; ++ char *p; ++ char *token; ++ long value; ++ u32 reg; ++ struct phytium_spi *fts = dev_get_drvdata(dev); ++ ++ dev_info(dev, "echo alive(1)/debug(0) enable(1)/disable(0) > debug\n"); ++ dev_info(dev, "Example:echo 0 1 > debug; Enable Debug Function\n"); ++ ++ p = kmalloc(size, GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ strscpy(p, buf, size); ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ ++ status = kstrtol(token, 0, &value); ++ if (status) ++ return status; ++ loc = (u8)value; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ ++ status = kstrtol(token, 0, &value); ++ if (status) ++ return status; ++ dis_en = value; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ ++ if (loc == 1) { ++ if (dis_en == 1) { ++ fts->alive_enabled = true; ++ reg |= BIT(loc); ++ } else if (dis_en == 0) { ++ fts->alive_enabled = false; ++ reg &= ~BIT(loc); ++ } ++ fts->runtimes = 0; ++ } else if (loc == 0) { ++ if (dis_en == 1) { ++ fts->debug_enabled = true; ++ reg |= BIT(loc); ++ } else if (dis_en == 0) { ++ fts->debug_enabled = false; ++ reg &= ~BIT(loc); ++ } ++ } ++ ++ phytium_write_regfile(fts, SPI_REGFILE_DEBUG, reg); ++ ++ kfree(p); ++ ++ return size; ++} ++ ++static DEVICE_ATTR_RW(debug); ++ ++static struct attribute *spi_phyt_device_attrs[] = { ++ &dev_attr_debug.attr, ++ NULL, ++}; ++ ++static const struct attribute_group spi_phyt_device_group = { ++ .attrs = spi_phyt_device_attrs, ++}; ++ ++static int spi_phyt_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phytium_spi *fts; ++ struct resource *regfile_mem, *share_mem; ++ int ret; ++ int num_cs; ++ int cs_gpio; ++ int global_cs = 0; ++ int i; ++ u32 clk_rate = SPI_DEFAULT_CLK; ++ ++ fts = devm_kzalloc(&pdev->dev, sizeof(struct phytium_spi), ++ GFP_KERNEL); ++ if (!fts) ++ return -ENOMEM; ++ ++ regfile_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regfile_mem) { ++ dev_err(&pdev->dev, "no regfile_mem resource?\n"); ++ return -EINVAL; ++ } ++ ++ fts->regfile = devm_ioremap_resource(&pdev->dev, regfile_mem); ++ if (IS_ERR(fts->regfile)) { ++ dev_err(&pdev->dev, "fts->regfile map failed\n"); ++ return PTR_ERR(fts->regfile); ++ } ++ ++ share_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!share_mem) { ++ dev_err(&pdev->dev, "no share_mem resource?\n"); ++ return -EINVAL; ++ } ++ ++ fts->mem_tx_physic = (u32)share_mem->start + sizeof(struct msg); ++ fts->mem_rx_physic = (u32)share_mem->start + sizeof(struct msg); ++ ++ fts->tx_shmem_addr = devm_ioremap_resource(&pdev->dev, share_mem); ++ if (IS_ERR(fts->tx_shmem_addr)) { ++ dev_err(&pdev->dev, "fts->tx_shmem_addr map failed\n"); ++ return PTR_ERR(fts->tx_shmem_addr); ++ } ++ ++ fts->msg = (struct msg *)fts->tx_shmem_addr; ++ ++ fts->mem_tx = (u64)fts->msg + sizeof(struct msg); ++ fts->mem_rx = (u64)fts->msg + sizeof(struct msg); ++ ++ fts->irq = platform_get_irq(pdev, 0); ++ if (fts->irq < 0) { ++ dev_err(&pdev->dev, "no irq resource?\n"); ++ return fts->irq; /* -ENXIO */ ++ } ++ ++ if (pdev->dev.of_node) { ++ fts->clk = devm_clk_get(&pdev->dev, NULL); ++ ++ if (IS_ERR(fts->clk)) ++ return PTR_ERR(fts->clk); ++ ret = clk_prepare_enable(fts->clk); ++ if (ret) ++ return ret; ++ ++ fts->max_freq = clk_get_rate(fts->clk); ++ } else if (has_acpi_companion(&pdev->dev)) { ++ fwnode_property_read_u32(dev->fwnode, "spi-clock", &clk_rate); ++ fts->max_freq = clk_rate; ++ } ++ ++ fts->bus_num = pdev->id; ++ device_property_read_u32(&pdev->dev, "reg-io-width", &fts->reg_io_width); ++ ++ num_cs = 4; ++ ++ device_property_read_u32(&pdev->dev, "num-cs", &num_cs); ++ ++ fts->num_cs = num_cs; ++ ++ if (pdev->dev.of_node) { ++ int i; ++ ++ for (i = 0; i < fts->num_cs; i++) { ++ cs_gpio = of_get_named_gpio(pdev->dev.of_node, ++ "cs-gpios", i); ++ ++ if (cs_gpio == -EPROBE_DEFER) { ++ ret = cs_gpio; ++ goto out; ++ } ++ ++ if (gpio_is_valid(cs_gpio)) { ++ ret = devm_gpio_request(&pdev->dev, cs_gpio, ++ dev_name(&pdev->dev)); ++ if (ret) ++ goto out; ++ } ++ } ++ } else if (has_acpi_companion(&pdev->dev)) { ++ int n; ++ int *cs; ++ struct gpio_desc *gpiod; ++ ++ n = gpiod_count(&pdev->dev, "cs"); ++ ++ cs = devm_kcalloc(&pdev->dev, n, sizeof(int), GFP_KERNEL); ++ fts->cs = cs; ++ ++ for (i = 0; i < n; i++) { ++ gpiod = devm_gpiod_get_index_optional(&pdev->dev, "cs", i, ++ GPIOD_OUT_LOW); ++ ++ if (IS_ERR(gpiod)) { ++ ret = PTR_ERR(gpiod); ++ goto out; ++ } ++ ++ cs_gpio = desc_to_gpio(gpiod); ++ cs[i] = cs_gpio; ++ } ++ } ++ ++ device_property_read_u32(&pdev->dev, "global-cs", &global_cs); ++ fts->global_cs = global_cs; ++ ++ fts->dma_get_ddrdata = false; ++ if ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FTC872) ++ fts->dma_get_ddrdata = true; ++ ++ ret = spi_phyt_add_host(&pdev->dev, fts); ++ if (ret) ++ goto out; ++ ++ platform_set_drvdata(pdev, fts); ++ ++ if (sysfs_create_group(&pdev->dev.kobj, &spi_phyt_device_group)) ++ dev_warn(&pdev->dev, "failed create sysfs\n"); ++ ++ return 0; ++ ++out: ++ clk_disable_unprepare(fts->clk); ++ return ret; ++} ++ ++static int spi_phyt_remove(struct platform_device *pdev) ++{ ++ struct phytium_spi *fts = platform_get_drvdata(pdev); ++ ++ spi_phyt_remove_host(fts); ++ sysfs_remove_group(&pdev->dev.kobj, &spi_phyt_device_group); ++ clk_disable_unprepare(fts->clk); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int spi_phyt_suspend(struct device *dev) ++{ ++ struct phytium_spi *fts = dev_get_drvdata(dev); ++ ++ return spi_phyt_suspend_host(fts); ++} ++ ++static int spi_phyt_resume(struct device *dev) ++{ ++ struct phytium_spi *fts = dev_get_drvdata(dev); ++ ++ return spi_phyt_resume_host(fts); ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(spi_phyt_pm_ops, spi_phyt_suspend, spi_phyt_resume); ++ ++static const struct of_device_id spi_phyt_of_match[] = { ++ { .compatible = "phytium,spi-2.0", .data = (void *)0 }, ++ { /* end of table */} ++}; ++MODULE_DEVICE_TABLE(of, spi_phyt_of_match); ++ ++static const struct acpi_device_id spi_phyt_acpi_match[] = { ++ {"PHYT0060", 0}, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, spi_phyt_acpi_match); ++ ++static struct platform_driver spi_phyt_driver = { ++ .probe = spi_phyt_probe, ++ .remove = spi_phyt_remove, ++ .driver = { ++ .name = DRIVER_NAME_PHYT, ++ .of_match_table = of_match_ptr(spi_phyt_of_match), ++ .acpi_match_table = ACPI_PTR(spi_phyt_acpi_match), ++ .pm = &spi_phyt_pm_ops, ++ }, ++}; ++module_platform_driver(spi_phyt_driver); ++ ++MODULE_AUTHOR("Peng Min "); ++MODULE_DESCRIPTION("Platform Driver for Phytium SPI controller core"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c +index 57593cd0e85b..11479fcfe053 100644 +--- a/drivers/spi/spi-phytium-plat.c ++++ b/drivers/spi/spi-phytium-plat.c +@@ -25,16 +25,21 @@ + #include "spi-phytium.h" + + #define DRIVER_NAME "phytium_spi" ++#define DRIVER_VERSION "1.0.0" ++ ++#define SPI_PHYTIUM_DEFAULT_CLK_RATE 50000000 + + static int phytium_spi_probe(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct phytium_spi *fts; + struct resource *mem; + int ret; + int num_cs; + int cs_gpio; +- int global_cs; ++ int global_cs = 0; + int i; ++ u32 clk_rate = SPI_PHYTIUM_DEFAULT_CLK_RATE; + + fts = devm_kzalloc(&pdev->dev, sizeof(struct phytium_spi), + GFP_KERNEL); +@@ -71,7 +76,9 @@ static int phytium_spi_probe(struct platform_device *pdev) + + fts->max_freq = clk_get_rate(fts->clk); + } else if (has_acpi_companion(&pdev->dev)) { +- fts->max_freq = 48000000; ++ fts->max_freq = clk_rate; ++ if (!fwnode_property_read_u32(dev->fwnode, "spi-clock", &clk_rate)) ++ fts->max_freq = clk_rate; + } + + fts->bus_num = pdev->id; +@@ -202,3 +209,4 @@ module_platform_driver(phytium_spi_driver); + MODULE_AUTHOR("Yiqun Zhang "); + MODULE_DESCRIPTION("Platform Driver for Phytium SPI controller core"); + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c +index 8695b627c85c..b9ee1d455d26 100755 +--- a/drivers/spi/spi-phytium-qspi.c ++++ b/drivers/spi/spi-phytium-qspi.c +@@ -5,6 +5,7 @@ + * Copyright (c) 2022-2024 Phytium Technology Co., Ltd. + */ + ++#include + #include + #include + #include +@@ -20,8 +21,14 @@ + #include + #include + ++#define DRIVER_VERSION "1.0.2" ++ ++#define PHYTIUM_CPU_PART_FTC862 0x862 ++ ++#define MIDR_PHYTIUM_FTC862 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC862) + + #define QSPI_FLASH_CAP_REG 0x00 ++#define QSPI_FLASH_CAP_NUM_SHIFT_NEW 16 + #define QSPI_FLASH_CAP_NUM_SHIFT 3 + #define QSPI_FLASH_CAP_NUM_MASK (0x3 << QSPI_FLASH_CAP_NUM_SHIFT) + #define QSPI_FLASH_CAP_CAP_SHIFT 0 +@@ -145,6 +152,10 @@ + #define XFER_PROTO_2_2_2 0x5 + #define XFER_PROTO_4_4_4 0x6 + ++#define WR_CFG_NODIR_VALUE 0x5000000 ++ ++#define QSPI_DEFAULT_CLK 500000000 ++ + struct phytium_qspi_flash { + u32 cs; + u32 clk_div; +@@ -249,6 +260,43 @@ static int phytium_spi_nor_protocol_encode(const struct spi_mem_op *op, u32 *cod + return ret; + } + ++static int phytium_qspi_flash_capacity_encode_new(u32 size, ++ u32 *cap, int i) ++{ ++ int ret = 0; ++ ++ switch (size) { ++ case SZ_4M: ++ *cap |= (0x0 << (4 * i)); ++ break; ++ case SZ_8M: ++ *cap |= (0x1 << (4 * i)); ++ break; ++ case SZ_16M: ++ *cap |= (0x2 << (4 * i)); ++ break; ++ case SZ_32M: ++ *cap |= (0x3 << (4 * i)); ++ break; ++ case SZ_64M: ++ *cap |= (0x4 << (4 * i)); ++ break; ++ case SZ_128M: ++ *cap |= (0x5 << (4 * i)); ++ break; ++ case SZ_256M: ++ *cap |= (0x6 << (4 * i)); ++ break; ++ case SZ_512M: ++ *cap |= (0x7 << (4 * i)); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ + static int phytium_qspi_flash_capacity_encode(u32 size, u32 *cap) + { + int ret = 0; +@@ -286,29 +334,6 @@ static int phytium_qspi_flash_capacity_encode(u32 size, u32 *cap) + return ret; + } + +-static void phytium_qspi_clear_wr(struct phytium_qspi *qspi, +- struct phytium_qspi_flash *flash) +-{ +- u32 cmd = 0; +- u32 state = 0; +- int ret = 0; +- +- cmd |= 0x05 << QSPI_CMD_PORT_CMD_SHIFT; +- cmd |= BIT(QSPI_CMD_PORT_TRANSFER_SHIFT); +- cmd |= flash->cs << QSPI_CMD_PORT_CS_SHIFT; +- +- writel_relaxed(cmd, qspi->io_base + QSPI_CMD_PORT_REG); +- readl_relaxed(qspi->io_base + QSPI_LD_PORT_REG); +- +- ret = readl_poll_timeout(qspi->io_base + QSPI_LD_PORT_REG, +- state, !(state & 0x01), 10, 100000); +- if (ret) +- dev_err(qspi->dev, "wait device timeout\n"); +- +- /* clear wr_cfg */ +- writel_relaxed(0x0, qspi->io_base + QSPI_WR_CFG_REG); +-} +- + static int phytium_qspi_write_port(struct phytium_qspi *qspi, + const u8 *buf, const size_t len) + { +@@ -421,8 +446,8 @@ static int phytium_qspi_exec_op(struct spi_mem *mem, + + if (op->dummy.nbytes) { + cmd |= QSPI_CMD_PORT_LATENCY_MASK; +- cmd |= ((op->dummy.nbytes * 8) / op->dummy.buswidth) << +- QSPI_CMD_PORT_LATENCY_SHIFT; ++ cmd |= ((op->dummy.nbytes * 8 - 1) / op->dummy.buswidth) << ++ QSPI_CMD_PORT_DUMMY_SHIFT; + } + + if (op->data.nbytes) { +@@ -513,6 +538,7 @@ static int phytium_qspi_dirmap_create(struct spi_mem_dirmap_desc *desc) + + cmd |= QSPI_WR_CFG_WR_MODE_MASK; + cmd |= flash->clk_div & QSPI_WR_CFG_WR_SCK_SEL_MASK; ++ writel_relaxed(cmd, qspi->io_base + QSPI_WR_CFG_REG); + qspi->wr_cfg_reg = cmd; + } else { + ret = -EINVAL; +@@ -550,9 +576,6 @@ static ssize_t phytium_qspi_dirmap_write(struct spi_mem_dirmap_desc *desc, + size_t mask = 0x03; + u_char tmp[4] = {0}; + +- /* set wr_cfg for drimap write */ +- writel_relaxed(qspi->wr_cfg_reg, qspi->io_base + QSPI_WR_CFG_REG); +- + if (offs & 0x03) { + dev_err(qspi->dev, "Addr not four-byte aligned!\n"); + return -EINVAL; +@@ -570,8 +593,6 @@ static ssize_t phytium_qspi_dirmap_write(struct spi_mem_dirmap_desc *desc, + //write cache data to flash + writel_relaxed(QSPI_FLUSH_EN, qspi->io_base + QSPI_FLUSH_REG); + +- phytium_qspi_clear_wr(qspi, flash); +- + return len; + } + +@@ -647,6 +668,8 @@ static int phytium_qspi_probe(struct platform_device *pdev) + int i, ret; + struct spi_mem *mem; + struct spi_nor *nor; ++ bool new_capacity = false; ++ u32 clk_rate = QSPI_DEFAULT_CLK; + + ctrl = spi_alloc_master(dev, sizeof(*qspi)); + if (!ctrl) +@@ -683,29 +706,34 @@ static int phytium_qspi_probe(struct platform_device *pdev) + } + qspi->used_size = 0; + +- qspi->clk = devm_clk_get(dev, NULL); +- if (IS_ERR(qspi->clk)) { +- ret = PTR_ERR(qspi->clk); +- goto probe_master_put; +- } ++ if (dev->of_node) { ++ qspi->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(qspi->clk)) { ++ ret = PTR_ERR(qspi->clk); ++ goto probe_master_put; ++ } + +- qspi->clk_rate = clk_get_rate(qspi->clk); +- if (!qspi->clk_rate) { +- ret = -EINVAL; +- goto probe_master_put; +- } ++ qspi->clk_rate = clk_get_rate(qspi->clk); ++ if (!qspi->clk_rate) { ++ ret = -EINVAL; ++ goto probe_master_put; ++ } + +- pm_runtime_enable(dev); +- ret = pm_runtime_get_sync(dev); +- if (ret < 0) { +- pm_runtime_put_noidle(dev); +- goto probe_master_put; +- } ++ pm_runtime_enable(dev); ++ ret = pm_runtime_get_sync(dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(dev); ++ goto probe_master_put; ++ } + +- ret = clk_prepare_enable(qspi->clk); +- if (ret) { +- dev_err(dev, "Failed to enable PCLK of the controller.\n"); +- goto probe_clk_failed; ++ ret = clk_prepare_enable(qspi->clk); ++ if (ret) { ++ dev_err(dev, "Failed to enable PCLK of the controller.\n"); ++ goto probe_clk_failed; ++ } ++ } else if (has_acpi_companion(dev)) { ++ fwnode_property_read_u32(dev->fwnode, "spi-clock", &clk_rate); ++ qspi->clk_rate = clk_rate; + } + + qspi->nodirmap = device_property_present(dev, "no-direct-mapping"); +@@ -713,6 +741,11 @@ static int phytium_qspi_probe(struct platform_device *pdev) + &phytium_qspi_mem_ops_nodirmap : + &phytium_qspi_mem_ops; + ++ if ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FTC862) { ++ dev_warn(dev, "capacity register(0x00) is the latest design\n"); ++ new_capacity = true; ++ } ++ + qspi->dev = dev; + platform_set_drvdata(pdev, qspi); + +@@ -722,7 +755,7 @@ static int phytium_qspi_probe(struct platform_device *pdev) + goto probe_setup_failed; + } + +- if (!qspi->nodirmap) { ++ if (!qspi->nodirmap && qspi->fnum != 0) { + /* + * The controller supports direct mapping access only if all + * flashes are of same size. +@@ -740,24 +773,37 @@ static int phytium_qspi_probe(struct platform_device *pdev) + } + } + +- for (i = 1; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { +- if (qspi->flash[i].size != qspi->flash[0].size) { +- dev_err(dev, "Flashes are of different sizes.\n"); +- ret = -EINVAL; +- goto probe_setup_failed; ++ if (!new_capacity) { ++ for (i = 1; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { ++ if (qspi->flash[i].size != qspi->flash[0].size) { ++ dev_err(dev, "Flashes are of different sizes.\n"); ++ ret = -EINVAL; ++ goto probe_setup_failed; ++ } + } ++ ret = phytium_qspi_flash_capacity_encode(qspi->flash[0].size, ++ &qspi->flash_cap); ++ if (ret) { ++ dev_err(dev, "Flash size is invalid.\n"); ++ goto probe_setup_failed; ++ } ++ qspi->flash_cap |= (qspi->fnum - 1) << QSPI_FLASH_CAP_NUM_SHIFT; ++ } else { ++ for (i = 0; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { ++ ret = phytium_qspi_flash_capacity_encode_new(qspi->flash[i].size, ++ &qspi->flash_cap, i); ++ if (ret) { ++ dev_err(dev, "Flash size is invalid.\n"); ++ goto probe_setup_failed; ++ } ++ } ++ qspi->flash_cap |= (qspi->fnum - 1) << QSPI_FLASH_CAP_NUM_SHIFT_NEW; + } + +- ret = phytium_qspi_flash_capacity_encode(qspi->flash[0].size, +- &qspi->flash_cap); +- if (ret) { +- dev_err(dev, "Flash size is invalid.\n"); +- goto probe_setup_failed; +- } +- +- qspi->flash_cap |= qspi->fnum << QSPI_FLASH_CAP_NUM_SHIFT; + + writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); ++ } else { ++ writel_relaxed(WR_CFG_NODIR_VALUE, qspi->io_base + QSPI_WR_CFG_REG); + } + + return 0; +@@ -796,6 +842,11 @@ static int phytium_qspi_remove(struct platform_device *pdev) + + static int __maybe_unused phytium_qspi_suspend(struct device *dev) + { ++ struct phytium_qspi *qspi = dev_get_drvdata(dev); ++ ++ /* clear rd_cfg reg and wr_cfg reg when suspend */ ++ writel_relaxed(0, qspi->io_base + QSPI_RD_CFG_REG); ++ writel_relaxed(0, qspi->io_base + QSPI_WR_CFG_REG); + return pm_runtime_force_suspend(dev); + } + +@@ -803,9 +854,14 @@ static int __maybe_unused phytium_qspi_resume(struct device *dev) + { + struct phytium_qspi *qspi = dev_get_drvdata(dev); + +- /* set rd_cfg reg and flash_capacity reg after resume */ +- writel_relaxed(qspi->rd_cfg_reg, qspi->io_base + QSPI_RD_CFG_REG); +- writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); ++ if (!qspi->nodirmap) { ++ /* set rd_cfg reg and flash_capacity reg after resume */ ++ writel_relaxed(qspi->rd_cfg_reg, qspi->io_base + QSPI_RD_CFG_REG); ++ writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); ++ } else { ++ writel_relaxed(WR_CFG_NODIR_VALUE, qspi->io_base + QSPI_WR_CFG_REG); ++ } ++ + return pm_runtime_force_resume(dev); + } + +@@ -834,3 +890,4 @@ module_platform_driver(phytium_qspi_driver); + MODULE_AUTHOR("Chen Baozi "); + MODULE_DESCRIPTION("Phytium Quad SPI driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c +new file mode 100644 +index 000000000000..81df999183b3 +--- /dev/null ++++ b/drivers/spi/spi-phytium-v2.c +@@ -0,0 +1,517 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Phytium SPI core controller driver. ++ * ++ * Copyright (c) 2023-2024, Phytium Technology Co., Ltd.. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "spi-phytium.h" ++ ++static inline void spi_phyt_enable_chip(struct phytium_spi *fts, u8 enable) ++{ ++ u8 val = enable ? 1 : 2; ++ ++ spi_phytium_set_cmd8(fts, PHYTSPI_MSG_CMD_SET_MODULE_EN, val); ++} ++ ++static inline void spi_phyt_set_clk(struct phytium_spi *fts, u16 div) ++{ ++ u32 new_div = div; ++ ++ spi_phytium_set_cmd32(fts, PHYTSPI_MSG_CMD_SET_BAUDR, new_div); ++} ++ ++static inline void spi_phyt_dma_reset(struct phytium_spi *fts, u8 enable) ++{ ++ spi_phytium_set_cmd8(fts, PHYTSPI_MSG_CMD_SET_DMA_RESET, enable); ++} ++ ++static inline void spi_phyt_global_cs(struct phytium_spi *fts) ++{ ++ u32 global_cs_en; ++ u16 cs; ++ ++ global_cs_en = GENMASK(fts->num_cs-1, 0) << fts->num_cs; ++ ++ cs = (u16)((0x1 << 8) | global_cs_en); ++ spi_phytium_set_cmd16(fts, PHYTSPI_MSG_CMD_SET_CS, cs); ++} ++ ++static inline void spi_phyt_reset_chip(struct phytium_spi *fts) ++{ ++ spi_phyt_dma_reset(fts, 1); ++ spi_phyt_enable_chip(fts, 0); ++ if (fts->global_cs) ++ spi_phyt_global_cs(fts); ++ spi_phyt_enable_chip(fts, 1); ++} ++ ++static inline void spi_phyt_shutdown_chip(struct phytium_spi *fts) ++{ ++ spi_phyt_enable_chip(fts, 0); ++ spi_phyt_set_clk(fts, 0); ++} ++ ++struct phytium_spi_chip { ++ u8 poll_mode; ++ u8 type; ++ void (*cs_control)(u32 command); ++}; ++ ++struct chip_data { ++ u8 cs; ++ u8 tmode; ++ u8 type; ++ ++ u8 poll_mode; ++ ++ u16 clk_div; ++ u32 speed_hz; ++ void (*cs_control)(u32 command); ++}; ++ ++static void spi_phyt_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct phytium_spi *fts = spi_master_get_devdata(spi->master); ++ struct chip_data *chip = spi_get_ctldata(spi); ++ u32 origin; ++ u16 cs; ++ ++ if (fts->tx || fts->rx) ++ return; ++ ++ if (fts->msg->cmd_id == PHYTSPI_MSG_CMD_DATA && ++ fts->msg->cmd_subid == PHYTSPI_MSG_CMD_DATA_TX) ++ return; ++ ++ if (chip && chip->cs_control) ++ chip->cs_control(!enable); ++ ++ if (!enable) { ++ cs = BIT(spi->chip_select); ++ spi_phytium_set_cmd16(fts, PHYTSPI_MSG_CMD_SET_CS, cs); ++ if (fts->global_cs) { ++ origin = (GENMASK(fts->num_cs-1, 0) << fts->num_cs) ++ | (1 << spi->chip_select); ++ cs = (0x1 << 8) | origin; ++ spi_phytium_set_cmd16(fts, PHYTSPI_MSG_CMD_SET_CS, cs); ++ } ++ } else { ++ if (fts->global_cs) { ++ origin = (GENMASK(fts->num_cs-1, 0) << fts->num_cs) ++ & ~(1 << spi->chip_select); ++ cs = (0x1 << 8) | origin; ++ spi_phytium_set_cmd16(fts, PHYTSPI_MSG_CMD_SET_CS, cs); ++ } ++ } ++} ++ ++static irqreturn_t spi_phyt_irq(int irq, void *dev_id) ++{ ++ struct spi_master *master = dev_id; ++ struct phytium_spi *fts = spi_master_get_devdata(master); ++ ++ complete(&fts->cmd_completion); ++ writel_relaxed(0, fts->regfile + SPI_REGFILE_RV2AP_INTR_STATE); ++ writel_relaxed(0x10, fts->regfile + SPI_REGFILE_RV2AP_INT_CLEAN); ++ ++ return IRQ_HANDLED; ++} ++ ++static int spi_phyt_transfer_one(struct spi_master *master, ++ struct spi_device *spi, struct spi_transfer *transfer) ++{ ++ struct phytium_spi *fts = spi_master_get_devdata(master); ++ struct chip_data *chip = spi_get_ctldata(spi); ++ int ret = 0; ++ ++ fts->tx = (void *)transfer->tx_buf; ++ fts->tx_end = fts->tx + transfer->len; ++ fts->rx = transfer->rx_buf; ++ fts->rx_end = fts->rx + transfer->len; ++ fts->len = transfer->len; ++ ++ if (chip->cs_control) { ++ if (fts->rx && fts->tx) ++ chip->tmode = TMOD_TR; ++ else if (fts->rx) ++ chip->tmode = TMOD_RO; ++ else ++ chip->tmode = TMOD_TO; ++ } ++ ++ if (fts->tx) { ++ if ((*(u8 *)fts->tx == SPINOR_OP_WREN) && fts->spi_write_flag == 0) { ++ spi_phytium_write_pre(fts, spi->chip_select, ++ transfer->bits_per_word, spi->mode, ++ chip->tmode, 3, fts->spi_write_flag); ++ fts->spi_write_flag++; ++ return 0; ++ } ++ ++ if ((*(u8 *)fts->tx == SPINOR_OP_BE_4K) && (fts->spi_write_flag == 1) && ++ fts->flash_read == 0 && fts->flash_erase != 1) { ++ fts->spi_write_flag++; ++ fts->flash_erase = 1; ++ return 0; ++ } ++ ++ if ((*(u8 *)fts->tx == SPINOR_OP_CHIP_ERASE) && (fts->spi_write_flag == 1) && ++ fts->flash_read == 0 && fts->flash_erase == 0) { ++ ret = spi_phytium_flash_erase(fts, spi->chip_select, ++ transfer->bits_per_word, ++ spi->mode, chip->tmode, 3, SPINOR_OP_CHIP_ERASE); ++ fts->spi_write_flag = 0; ++ fts->flash_erase = 2; ++ } ++ ++ if ((*(u8 *)fts->tx == SPINOR_OP_READ || *(u8 *)fts->tx == SPINOR_OP_READ_FAST || ++ *(u8 *)fts->tx == SPINOR_OP_READ_4B || ++ *(u8 *)fts->tx == SPINOR_OP_READ_FAST_4B) && ++ fts->spi_write_flag == 0 && fts->flash_read == 0 && ++ fts->flash_erase == 0) { ++ fts->flash_cmd = *(u8 *)fts->tx; ++ fts->spi_write_flag++; ++ fts->flash_read = 1; ++ return 0; ++ } ++ ++ if ((fts->spi_write_flag == 1) && fts->flash_read == 0 && ++ fts->flash_write == 0 && ((*(u8 *)fts->tx == SPINOR_OP_PP) || ++ (*(u8 *)fts->tx == SPINOR_OP_PP_4B))) { ++ fts->flash_cmd = *(u8 *)fts->tx; ++ fts->spi_write_flag++; ++ fts->flash_write = 1; ++ return 0; ++ } ++ ++ if ((*(u8 *)fts->tx == SPINOR_OP_RDSR) && fts->flash_write == 3) { ++ fts->read_sr = 1; ++ fts->flash_write = 0; ++ return 0; ++ } ++ ++ if ((*(u8 *)fts->tx == SPINOR_OP_RDSR) && fts->flash_erase == 2) { ++ fts->read_sr = 1; ++ return 0; ++ } ++ } ++ ++ if (fts->read_sr) { ++ *(u8 *)(fts->rx) = 0; ++ fts->read_sr = 0; ++ return 0; ++ } ++ ++ if (fts->tx) { ++ if (fts->flash_erase == 1) { ++ ret = spi_phytium_flash_erase(fts, spi->chip_select, ++ transfer->bits_per_word, ++ spi->mode, chip->tmode, 3, SPINOR_OP_BE_4K); ++ if (ret) { ++ dev_err(&master->dev, "flash erase failed\n"); ++ return ret; ++ } ++ fts->spi_write_flag = 0; ++ fts->flash_erase++; ++ } else if (fts->flash_read) { ++ ret = spi_phytium_flash_erase(fts, spi->chip_select, ++ transfer->bits_per_word, ++ spi->mode, chip->tmode, 1, fts->flash_cmd); ++ if (ret) { ++ dev_err(&master->dev, "transfer read-command failed\n"); ++ return ret; ++ } ++ fts->spi_write_flag = 0; ++ fts->flash_read = 0; ++ } else if (fts->flash_write == 1) { ++ fts->flash_write++; ++ ret = spi_phytium_flash_write(fts, fts->flash_cmd); ++ if (ret) { ++ dev_err(&master->dev, "flash write failed\n"); ++ return ret; ++ } ++ } else if (fts->flash_erase == 2 && (*(u8 *)fts->tx == SPINOR_OP_WRDI)) { ++ ret = spi_phytium_write(fts, spi->chip_select, transfer->bits_per_word, ++ spi->mode, chip->tmode, 3, fts->spi_write_flag); ++ if (ret) { ++ dev_err(&master->dev, "transfer disable-command failed\n"); ++ return ret; ++ } ++ fts->flash_erase = 0; ++ } else { ++ ret = spi_phytium_write(fts, spi->chip_select, transfer->bits_per_word, ++ spi->mode, chip->tmode, 1, fts->spi_write_flag); ++ if (ret) { ++ dev_err(&master->dev, "write command failed\n"); ++ return ret; ++ } ++ if (fts->flash_write == 2) ++ fts->flash_write++; ++ fts->spi_write_flag = 0; ++ } ++ } ++ ++ if (fts->rx) { ++ ret = spi_phytium_read(fts, spi->chip_select, transfer->bits_per_word, ++ spi->mode, chip->tmode, 2); ++ if (ret) { ++ dev_err(&master->dev, "read data failed\n"); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ ++static void spi_phyt_handle_err(struct spi_master *master, ++ struct spi_message *msg) ++{ ++ struct phytium_spi *fts = spi_master_get_devdata(master); ++ ++ spi_phyt_reset_chip(fts); ++} ++ ++static int spi_phyt_setup(struct spi_device *spi) ++{ ++ struct phytium_spi_chip *chip_info = NULL; ++ struct chip_data *chip; ++ struct spi_master *master = spi->master; ++ struct phytium_spi *fts = spi_master_get_devdata(master); ++ u8 data_width, scph, scpol, tmode; ++ u16 mode; ++ u16 clk_div; ++ ++ spi_phyt_enable_chip(fts, 0); ++ ++ clk_div = (fts->max_freq / spi->max_speed_hz + 1) & 0xfffe; ++ spi_phyt_set_clk(fts, clk_div); ++ fts->clk_div = clk_div; ++ ++ chip = spi_get_ctldata(spi); ++ if (!chip) { ++ chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); ++ if (!chip) ++ return -ENOMEM; ++ spi_set_ctldata(spi, chip); ++ } ++ ++ chip_info = spi->controller_data; ++ ++ if (chip_info) { ++ if (chip_info->cs_control) ++ chip->cs_control = chip_info->cs_control; ++ ++ chip->poll_mode = chip_info->poll_mode; ++ chip->type = chip_info->type; ++ } ++ ++ chip->tmode = 0; ++ ++ data_width = spi->bits_per_word; ++ spi_phytium_set_cmd8(fts, PHYTSPI_MSG_CMD_SET_DATA_WIDTH, data_width); ++ ++ scph = spi->mode & (0x1); ++ scpol = spi->mode >> 1; ++ mode = (scph << 8) | scpol; ++ spi_phytium_set_cmd16(fts, PHYTSPI_MSG_CMD_SET_MODE, mode); ++ ++ tmode = chip->tmode; ++ spi_phytium_set_cmd8(fts, PHYTSPI_MSG_CMD_SET_TMOD, tmode); ++ ++ spi_phyt_enable_chip(fts, 1); ++ ++ return 0; ++} ++ ++static void spi_phyt_cleanup(struct spi_device *spi) ++{ ++ struct chip_data *chip = spi_get_ctldata(spi); ++ ++ kfree(chip); ++ spi_set_ctldata(spi, NULL); ++} ++ ++void spi_phyt_enable_debug(struct phytium_spi *fts) ++{ ++ u32 reg; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ ++ phytium_write_regfile(fts, SPI_REGFILE_DEBUG, ++ reg | SPI_REGFILE_DEBUG_VAL); ++} ++ ++void spi_phyt_disable_debug(struct phytium_spi *fts) ++{ ++ u32 reg; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ reg &= ~SPI_REGFILE_DEBUG_VAL; ++ ++ phytium_write_regfile(fts, SPI_REGFILE_DEBUG, reg); ++} ++ ++void spi_phyt_disable_alive(struct phytium_spi *fts) ++{ ++ u32 reg; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ reg &= ~SPI_REGFILE_ALIVE_VAL; ++ ++ phytium_write_regfile(fts, SPI_REGFILE_DEBUG, reg); ++} ++ ++void spi_watchdog(struct phytium_spi *fts) ++{ ++ u32 reg; ++ ++ reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); ++ phytium_write_regfile(fts, SPI_REGFILE_DEBUG, ++ reg | SPI_REGFILE_HEARTBIT_VAL); ++} ++ ++static void spi_phyt_timer_handle(struct timer_list *t) ++{ ++ struct phytium_spi *fts = from_timer(fts, t, timer); ++ ++ if (fts->alive_enabled && fts->watchdog) { ++ if (fts->runtimes < 20) ++ fts->watchdog(fts); ++ ++ fts->runtimes++; ++ } ++ ++ mod_timer(&fts->timer, jiffies + msecs_to_jiffies(10)); ++} ++ ++static void spi_phyt_hw_init(struct device *dev, struct phytium_spi *fts) ++{ ++ spi_phytium_default(fts); ++} ++ ++int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts) ++{ ++ struct spi_master *master; ++ int ret; ++ ++ WARN_ON(fts == NULL); ++ ++ master = spi_alloc_master(dev, 0); ++ if (!master) ++ return -ENOMEM; ++ ++ fts->master = master; ++ snprintf(fts->name, sizeof(fts->name), "phytium_spi%d", fts->bus_num); ++ ++ init_completion(&fts->cmd_completion); ++ ret = devm_request_irq(dev, fts->irq, spi_phyt_irq, IRQF_SHARED, fts->name, master); ++ if (ret < 0) { ++ dev_err(dev, "can not get IRQ\n"); ++ goto err_free_master; ++ } ++ ++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; ++ master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); ++ master->bus_num = fts->bus_num; ++ master->num_chipselect = fts->num_cs; ++ master->setup = spi_phyt_setup; ++ master->cleanup = spi_phyt_cleanup; ++ master->set_cs = spi_phyt_set_cs; ++ master->transfer_one = spi_phyt_transfer_one; ++ master->handle_err = spi_phyt_handle_err; ++ master->max_speed_hz = fts->max_freq; ++ master->dev.of_node = dev->of_node; ++ master->dev.fwnode = dev->fwnode; ++ master->flags = SPI_MASTER_GPIO_SS; ++ ++ spi_master_set_devdata(master, fts); ++ ++ spi_phyt_disable_debug(fts); ++ spi_phyt_disable_alive(fts); ++ fts->runtimes = 0; ++ fts->debug_enabled = false; ++ fts->alive_enabled = false; ++ ++ fts->watchdog = spi_watchdog; ++ ++ fts->timer.expires = jiffies + msecs_to_jiffies(50); ++ timer_setup(&fts->timer, spi_phyt_timer_handle, 0); ++ add_timer(&fts->timer); ++ ++ spi_phyt_hw_init(dev, fts); ++ ++ ret = devm_spi_register_master(dev, master); ++ if (ret) { ++ dev_err(&master->dev, "problem registering spi master\n"); ++ goto err_exit; ++ } ++ ++ return 0; ++ ++err_exit: ++ spi_phyt_enable_chip(fts, 0); ++err_free_master: ++ spi_master_put(master); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_phyt_add_host); ++ ++void spi_phyt_remove_host(struct phytium_spi *fts) ++{ ++ del_timer(&fts->timer); ++ spi_phyt_shutdown_chip(fts); ++} ++EXPORT_SYMBOL_GPL(spi_phyt_remove_host); ++ ++int spi_phyt_suspend_host(struct phytium_spi *fts) ++{ ++ int ret; ++ ++ ret = spi_controller_suspend(fts->master); ++ if (ret) ++ return ret; ++ ++ spi_phyt_shutdown_chip(fts); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(spi_phyt_suspend_host); ++ ++int spi_phyt_resume_host(struct phytium_spi *fts) ++{ ++ int ret; ++ ++ spi_phyt_hw_init(&fts->master->dev, fts); ++ ++ spi_phyt_enable_chip(fts, 0); ++ spi_phyt_set_clk(fts, fts->clk_div); ++ spi_phyt_enable_chip(fts, 1); ++ ++ ret = spi_controller_resume(fts->master); ++ if (ret) ++ dev_err(&fts->master->dev, "fail to start queue (%d)\n", ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_phyt_resume_host); ++ ++MODULE_AUTHOR("Peng Min "); ++MODULE_DESCRIPTION("Driver for Phytium SPI controller core"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/spi/spi-phytium.h b/drivers/spi/spi-phytium.h +index 003b08f8c506..c328ddfa0773 100644 +--- a/drivers/spi/spi-phytium.h ++++ b/drivers/spi/spi-phytium.h +@@ -1,4 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Phytium SPI controller driver. ++ * ++ * Copyright (c) 2019-2023, Phytium Technology Co., Ltd. ++ */ + #ifndef PHYTIUM_SPI_HEADER_H + #define PHYTIUM_SPI_HEADER_H + +@@ -54,6 +59,81 @@ + + #define SPI_WAIT_RETRIES 5 + ++#define SPI_REGFILE_SIZE (0x48) ++#define SPI_REGFILE_AP2RV_INTR_STATE (0x24) ++#define SPI_REGFILE_RV2AP_INTR_STATE (0x2c) ++#define SPI_REGFILE_RV2AP_INT_CLEAN (0x74) ++#define SPI_REGFILE_DEBUG (0x58) ++ ++#define SPI_REGFILE_DEBUG_VAL BIT(0) ++#define SPI_REGFILE_ALIVE_VAL BIT(1) ++#define SPI_REGFILE_HEARTBIT_VAL BIT(2) ++ ++#define SPI_MODULE_OPT_CMD 0x20 ++ ++#define SPI_TRANS_DATA_SIZE 1024 ++#define FLASH_PAGE_SIZE 256 ++ ++#define SPI_MSG_COMPLETE_OK 1 ++#define SPI_MSG_COMPLETE_KO 0 ++ ++#define SPI_RESULT_IGNORE_LVL (0) ++#define SPI_RESULT_WRITE_ISR_LVL (1) ++#define SPI_RESULT_READ_ISR_LVL (2) ++ ++#define SPI_SHMEM_TX_MSG_MAX_CNT 1 ++ ++#define SPI_MASTER_TIMEOUT 8 ++ ++#define SPI_DEFAULT_CLK 50000000 ++ ++enum phytspi_msg_cmd_id { ++ PHYTSPI_MSG_CMD_DEFAULT = 0, ++ PHYTSPI_MSG_CMD_SET, ++ PHYTSPI_MSG_CMD_GET, ++ PHYTSPI_MSG_CMD_DATA, ++ PHYTSPI_MSG_CMD_REPORT, ++}; ++ ++enum phytspi_set_subid { ++ PHYTSPI_MSG_CMD_SET_MODULE_EN = 0, ++ PHYTSPI_MSG_CMD_SET_DATA_WIDTH, ++ PHYTSPI_MSG_CMD_SET_MODE, ++ PHYTSPI_MSG_CMD_SET_TMOD, ++ PHYTSPI_MSG_CMD_SET_BAUDR, ++ PHYTSPI_MSG_CMD_SET_INT_TI, ++ PHYTSPI_MSG_CMD_SET_NDF, ++ PHYTSPI_MSG_CMD_SET_CS, ++ PHYTSPI_MSG_CMD_SET_DMA_RESET, ++}; ++ ++enum phytspi_data_subid { ++ PHYTSPI_MSG_CMD_DATA_TX = 0, ++ PHYTSPI_MSG_CMD_DATA_RX, ++ PHYTSPI_MSG_CMD_DATA_FLASH_TX, ++ PHYTSPI_MSG_CMD_FLASH_ERASE, ++ PHYTSPI_MSG_CMD_DATA_DMA_TX, ++ PHYTSPI_MSG_CMD_DATA_DMA_RX, ++ PHYTSPI_MSG_CMD_DATA_FLASH_DMA_TX, ++}; ++ ++struct msg { ++ u8 reserved; ++ u8 seq; ++ u8 cmd_id; ++ u8 cmd_subid; ++ u16 len; ++ u8 status1; ++ u8 status0; ++ u8 data[56]; ++}; ++ ++struct spi_trans_msg_info { ++ u32 msg_total_num; ++ u32 shmem_data_addr; ++ int result; ++}; ++ + struct phytium_spi; + + struct phytium_spi_dma_ops { +@@ -71,8 +151,21 @@ struct phytium_spi { + char name[16]; + + void __iomem *regs; ++ void __iomem *regfile; ++ void __iomem *tx_shmem_addr; ++ void *rx_shmem_addr; ++ ++ struct msg *msg; ++ u32 mem_tx_physic; ++ u32 mem_rx_physic; ++ u64 mem_tx; ++ u64 mem_rx; ++ ++ u16 clk_div; ++ int module; ++ + bool global_cs; +- bool dma_en; ++ bool dma_en; + unsigned long paddr; + int irq; + u32 fifo_len; +@@ -92,9 +185,26 @@ struct phytium_spi { + int dma_mapped; + struct clk *clk; + irqreturn_t (*transfer_handler)(struct phytium_spi *fts); +- u32 current_freq; /* frequency in hz */ ++ ++ int cmd_err; ++ u32 cur_tx_tail; ++ struct completion cmd_completion; ++ ++ u8 spi_write_flag; ++ u8 flash_erase; ++ u8 flash_read; ++ u8 flash_write; ++ u8 read_sr; ++ u8 flash_cmd; ++ ++ bool debug_enabled; ++ bool alive_enabled; ++ struct timer_list timer; ++ u32 runtimes; // for debug ++ void (*watchdog)(struct phytium_spi *fts); + + /* DMA info */ ++ u32 current_freq; /* frequency in hz */ + struct dma_chan *txchan; + u32 txburst; + struct dma_chan *rxchan; +@@ -104,6 +214,8 @@ struct phytium_spi { + dma_addr_t dma_addr; /* phy address of the Data register */ + const struct phytium_spi_dma_ops *dma_ops; + struct completion dma_completion; ++ ++ bool dma_get_ddrdata; + }; + + static inline u32 phytium_readl(struct phytium_spi *fts, u32 offset) +@@ -115,17 +227,14 @@ static inline u16 phytium_readw(struct phytium_spi *fts, u32 offset) + { + return __raw_readw(fts->regs + offset); + } +- + static inline void phytium_writel(struct phytium_spi *fts, u32 offset, u32 val) + { + __raw_writel(val, fts->regs + offset); + } +- + static inline void phytium_writew(struct phytium_spi *fts, u32 offset, u16 val) + { + __raw_writew(val, fts->regs + offset); + } +- + static inline u32 phytium_read_io_reg(struct phytium_spi *fts, u32 offset) + { + switch (fts->reg_io_width) { +@@ -136,8 +245,8 @@ static inline u32 phytium_read_io_reg(struct phytium_spi *fts, u32 offset) + return phytium_readl(fts, offset); + } + } +- +-static inline void phytium_write_io_reg(struct phytium_spi *fts, u32 offset, u32 val) ++static inline void phytium_write_io_reg(struct phytium_spi *fts, ++ u32 offset, u32 val) + { + switch (fts->reg_io_width) { + case 2: +@@ -149,17 +258,14 @@ static inline void phytium_write_io_reg(struct phytium_spi *fts, u32 offset, u32 + break; + } + } +- + static inline void spi_enable_chip(struct phytium_spi *fts, int enable) + { + phytium_writel(fts, SSIENR, (enable ? 1 : 0)); + } +- + static inline void spi_set_clk(struct phytium_spi *fts, u16 div) + { + phytium_writel(fts, BAUDR, div); + } +- + static inline void spi_mask_intr(struct phytium_spi *fts, u32 mask) + { + u32 new_mask; +@@ -167,7 +273,6 @@ static inline void spi_mask_intr(struct phytium_spi *fts, u32 mask) + new_mask = phytium_readl(fts, IMR) & ~mask; + phytium_writel(fts, IMR, new_mask); + } +- + static inline void spi_umask_intr(struct phytium_spi *fts, u32 mask) + { + u32 new_mask; +@@ -175,7 +280,6 @@ static inline void spi_umask_intr(struct phytium_spi *fts, u32 mask) + new_mask = phytium_readl(fts, IMR) | mask; + phytium_writel(fts, IMR, new_mask); + } +- + static inline void spi_global_cs(struct phytium_spi *fts) + { + u32 global_cs_en, mask, setmask; +@@ -183,10 +287,8 @@ static inline void spi_global_cs(struct phytium_spi *fts) + mask = GENMASK(fts->num_cs-1, 0) << fts->num_cs; + setmask = ~GENMASK(fts->num_cs-1, 0); + global_cs_en = (phytium_readl(fts, GCSR) | mask) & setmask; +- + phytium_writel(fts, GCSR, global_cs_en); + } +- + static inline void spi_reset_chip(struct phytium_spi *fts) + { + spi_enable_chip(fts, 0); +@@ -195,7 +297,6 @@ static inline void spi_reset_chip(struct phytium_spi *fts) + spi_mask_intr(fts, 0xff); + spi_enable_chip(fts, 1); + } +- + static inline void spi_shutdown_chip(struct phytium_spi *fts) + { + spi_enable_chip(fts, 0); +@@ -203,6 +304,36 @@ static inline void spi_shutdown_chip(struct phytium_spi *fts) + fts->current_freq = 0; + } + ++static inline u32 phytium_read_regfile(struct phytium_spi *fts, u32 reg_off) ++{ ++ return readl_relaxed(fts->regfile + reg_off); ++} ++ ++static inline void phytium_write_regfile(struct phytium_spi *fts, u32 reg_off, u32 val) ++{ ++ writel_relaxed(val, fts->regfile + reg_off); ++} ++ ++extern void spi_phytium_default(struct phytium_spi *fts); ++extern void spi_phytium_set_cmd8(struct phytium_spi *fts, u16 sub_cmd, u8 data); ++extern void spi_phytium_set_cmd16(struct phytium_spi *fts, u16 sub_cmd, u16 data); ++extern void spi_phytium_set_cmd32(struct phytium_spi *fts, u16 sub_cmd, u32 data); ++extern void spi_phytium_data_cmd_write(struct phytium_spi *fts, u16 sub_cmd); ++extern void spi_phytium_data_cmd_read(struct phytium_spi *fts, u16 sub_cmd); ++extern void spi_phytium_write_pre(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, u8 tmode, ++ u8 flags, u8 spi_write_flag); ++extern int spi_phytium_flash_erase(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags, u8 cmd); ++extern int spi_phytium_flash_write(struct phytium_spi *fts, u8 cmd); ++extern int spi_phytium_write(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags, u8 spi_write_flag); ++extern int spi_phytium_read(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, ++ u8 tmode, u8 flags); ++extern int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts); ++extern void spi_phyt_remove_host(struct phytium_spi *fts); ++extern int spi_phyt_suspend_host(struct phytium_spi *fts); ++extern int spi_phyt_resume_host(struct phytium_spi *fts); ++ + extern int phytium_spi_add_host(struct device *dev, struct phytium_spi *fts); + extern void phytium_spi_remove_host(struct phytium_spi *fts); + extern int phytium_spi_suspend_host(struct phytium_spi *fts); +diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig +index 28f22e58639c..15c0f1fbb3f5 100644 +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -73,6 +73,26 @@ config SERIAL_AMBA_PL011_CONSOLE + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + ++config SERIAL_PHYTIUM_UART_V2 ++ tristate "Phytium V2 serial port support" ++ depends on ARCH_PHYTIUM ++ select SERIAL_CORE ++ help ++ This driver supports the Phytium UART V2 controller on platform adapters. ++ If you want to compile this driver into the kernel, say Y here. To ++ compile this driver as a module, choose M here. ++ ++ If unsure, say N. ++ ++config SERIAL_PHYTIUM_V2_DEBUG ++ bool "Phytium UART V2 debug/heartbeat function support" ++ depends on SERIAL_PHYTIUM_UART_V2 ++ help ++ This driver supports the Phytium UART V2 controller Debug on platform adapters. ++ If you want to enable debug, say Y here. ++ ++ If unsure, say N. ++ + config SERIAL_EARLYCON_ARM_SEMIHOST + bool "Early console using ARM semihosting" + depends on ARM64 || ARM +@@ -1583,6 +1603,17 @@ config SERIAL_MILBEAUT_USIO_CONSOLE + receives all kernel messages and warnings and which allows logins in + single user mode). + ++config SERIAL_PHYTIUM_PCI ++ tristate "Phytium PCI serial port support" ++ depends on PCI ++ select SERIAL_CORE ++ help ++ This driver supports the Phytium UART controller on PCI/PCIe adapters. ++ If you want to compile this driver into the kernel, say Y here. To ++ compile this driver as a module, choose M here. ++ ++ If unsure, say N. ++ + endmenu + + config SERIAL_MCTRL_GPIO +diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile +index caf167f0c10a..6b60242a4724 100644 +--- a/drivers/tty/serial/Makefile ++++ b/drivers/tty/serial/Makefile +@@ -90,6 +90,9 @@ obj-$(CONFIG_SERIAL_OWL) += owl-uart.o + obj-$(CONFIG_SERIAL_RDA) += rda-uart.o + obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o + obj-$(CONFIG_SERIAL_SIFIVE) += sifive.o ++obj-$(CONFIG_SERIAL_PHYTIUM_UART_V2) += phytium-uart-v2.o ++ ++obj-$(CONFIG_SERIAL_PHYTIUM_PCI) += phytium-uart.o + + # GPIOLIB helpers for modem control lines + obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o +diff --git a/drivers/tty/serial/phytium-uart-v2.c b/drivers/tty/serial/phytium-uart-v2.c +new file mode 100644 +index 000000000000..4905e25afffb +--- /dev/null ++++ b/drivers/tty/serial/phytium-uart-v2.c +@@ -0,0 +1,1384 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* Driver for phytium uart v2 ++ * Copyright (c) 2020-2025, Phytium Technology, Co., Ltd. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "phytium-uart-v2.h" ++#define cmd_id_type uint8_t ++#define cmd_subid_type uint8_t ++#define DEFAULT_CLK 10000000 ++#define PHYT_UART_DRV_VER "1.1.0" ++/* ++ * We wrap our port structure around the generic uart_port. ++ */ ++struct phytium_uart_port { ++ struct uart_port port; ++ unsigned int old_cr; /* state during shutdown */ ++ unsigned int old_status; ++ char type[12]; ++ struct device *dev; ++ struct clk *clk; ++ void __iomem *shmem_base; ++ bool m_buf_empty; ++ bool heartbeat_enable_flag; ++ bool debug_enable_flag; ++ struct timer_list alive_timer; ++}; ++ ++/* define msg format */ ++struct msg { ++ u16 module_id; ++ u8 cmd_id; ++ u8 cmd_subid; ++ u16 length; ++ u16 complete; ++ u8 data[120]; ++}; ++ ++static unsigned int phytium_uart_read(const struct phytium_uart_port *pup, ++ unsigned int reg) ++{ ++ void __iomem *addr = pup->port.membase + reg; ++ ++ return readl_relaxed(addr); ++} ++ ++static void phytium_uart_write(unsigned int val, ++ const struct phytium_uart_port *pup, unsigned int reg) ++{ ++ void __iomem *addr = pup->port.membase + reg; ++ ++ writel_relaxed(val, addr); ++} ++ ++/* func for filling with msg */ ++static void msg_fill(struct msg *msg, u16 module_id, ++ u8 cmd_id, u8 cmd_subid, u16 complete) ++{ ++ msg->module_id = module_id; ++ msg->cmd_id = cmd_id; ++ msg->cmd_subid = cmd_subid; ++ msg->complete = complete; ++ ++ memset(msg->data, 0, sizeof(msg->data)); ++} ++ ++static int tx_ring_buffer_is_full(struct phytium_uart_port *pup) ++{ ++ u16 tx_tail, tx_head; ++ ++ tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ tx_head = phytium_uart_read(pup, REG_TX_HEAD) & BUFFER_POINTER_MASK; ++ ++ if (((tx_tail + 1) % TX_BUFFER_SIZE) == tx_head) ++ return 1; ++ ++ return 0; ++} ++ ++static int tx_ring_buffer_is_empty(struct phytium_uart_port *pup) ++{ ++ u16 tx_tail, tx_head; ++ ++ tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ tx_head = phytium_uart_read(pup, REG_TX_HEAD) & BUFFER_POINTER_MASK; ++ ++ if (tx_tail == tx_head) ++ return 1; ++ ++ return 0; ++} ++ ++static void PHYT_MSG_INSERT(struct phytium_uart_port *pup, struct msg *msg) ++{ ++ u16 tx_tail, tx_head; ++ ++ tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ tx_head = phytium_uart_read(pup, REG_TX_HEAD) & BUFFER_POINTER_MASK; ++ ++ pr_debug("TX_TAIL:%x, TX_HEAD:%x", tx_tail, tx_head); ++ ++ while (tx_ring_buffer_is_full(pup)) ++ cpu_relax(); ++ ++ memcpy(pup->shmem_base + TX_MSG_SIZE * tx_tail, ++ msg, sizeof(struct msg)); ++ ++ /* updata tx tail pointer */ ++ tx_tail = (tx_tail + 1) % TX_BUFFER_SIZE; ++ phytium_uart_write(tx_tail, pup, REG_TX_TAIL); ++ ++ phytium_uart_write(PHYT_INT_TRIGGER_BIT, pup, REG_PHYT_INT_STATE); ++} ++ ++ ++static int rx_ring_buffer_is_empty(struct phytium_uart_port *pup) ++{ ++ u16 rx_tail, rx_head; ++ ++ rx_tail = phytium_uart_read(pup, REG_RX_TAIL) & BUFFER_POINTER_MASK; ++ rx_head = phytium_uart_read(pup, REG_RX_HEAD) & BUFFER_POINTER_MASK; ++ if (rx_tail == rx_head) ++ return 1; ++ return 0; ++} ++ ++ ++static void phytium_fifo_to_tty(struct phytium_uart_port *pup) ++{ ++ struct msg *handler_msg; ++ int sysrq; ++ unsigned int ch, flag, fifotaken; ++ u16 count = 0; ++ u16 rx_head, rx_tail; ++ ++ while (!rx_ring_buffer_is_empty(pup)) { ++ rx_head = (phytium_uart_read(pup, REG_RX_HEAD) ++ & BUFFER_POINTER_MASK); ++ rx_tail = (phytium_uart_read(pup, REG_RX_TAIL) ++ & BUFFER_POINTER_MASK); ++ ++ /* get operator pointer of rv data msg */ ++ handler_msg = (struct msg *)(pup->shmem_base + TX_MSG_SIZE ++ * TX_BUFFER_SIZE + RX_MSG_SIZE * rx_head); ++ pr_debug("handler_msg = %p, rx_head=%d, rx_tail=%d\n", ++ handler_msg, rx_head, rx_tail); ++ if (!handler_msg) { ++ pr_err("%s cannot get msg!\n", __func__); ++ return; ++ } ++ count = handler_msg->length / 2; ++ ++ rx_head = (rx_head + 1) % RX_BUFFER_SIZE; ++ phytium_uart_write(rx_head, pup, REG_RX_HEAD); ++ ++ for (fifotaken = 0; fifotaken != RX_DATA_MAXINUM; fifotaken++) { ++ if (count == 0) ++ break; ++ count--; ++ /* Take chars maxinum 60 * 2 bytes from the MSG */ ++ ch = (handler_msg->data[2 * fifotaken]); ++ ch |= (handler_msg->data[2 * fifotaken + 1] << 8); ++ ch |= DATA_DUMMY_RX; ++ flag = TTY_NORMAL; ++ pup->port.icount.rx++; ++ ++ if (unlikely(ch & DATA_ERROR)) { ++ if (ch & DATA_BE) { ++ ch &= ~(DATA_FE | DATA_PE); ++ pup->port.icount.brk++; ++ if (uart_handle_break(&pup->port)) ++ continue; ++ } else if (ch & DATA_PE) ++ pup->port.icount.parity++; ++ else if (ch & DATA_FE) ++ pup->port.icount.frame++; ++ if (ch & DATA_OE) ++ pup->port.icount.overrun++; ++ ++ ch &= pup->port.read_status_mask; ++ ++ if (ch & DATA_BE) ++ flag = TTY_BREAK; ++ else if (ch & DATA_PE) ++ flag = TTY_PARITY; ++ else if (ch & DATA_FE) ++ flag = TTY_FRAME; ++ } ++ ++ spin_unlock(&pup->port.lock); ++ sysrq = uart_handle_sysrq_char(&pup->port, ++ ch & CHAR_MASK); ++ spin_lock(&pup->port.lock); ++ ++ if (!sysrq) ++ uart_insert_char(&pup->port, ch, ++ DATA_OE, ch, flag); ++ } ++ } ++} ++ ++static void phytium_rx_chars(struct phytium_uart_port *pup) ++__releases(&pup->port.lock) ++__acquires(&pup->port.lock) ++{ ++ phytium_fifo_to_tty(pup); ++ ++ spin_unlock(&pup->port.lock); ++ ++ tty_flip_buffer_push(&pup->port.state->port); ++ ++ spin_lock(&pup->port.lock); ++} ++ ++static void phytium_stop_tx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ unsigned int int_mask; ++ ++ if (!tx_ring_buffer_is_empty(pup)) ++ return; ++ /* mask tx msg tail pointer int*/ ++ int_mask = phytium_uart_read(pup, REG_RP_INT_MASK); ++ phytium_uart_write(int_mask | PHYT_MSG_DATA_COMPLETED, ++ pup, REG_RP_INT_MASK); ++ ++} ++ ++static bool phytium_tx_xchar(struct phytium_uart_port *pup, unsigned char c, ++ bool from_irq) ++{ ++ struct msg msg; ++ struct msg *handler_msg; ++ u16 count = 1; ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_DATA, MSG_TX_DATA, 0); ++ ++ handler_msg = (struct msg *)(pup->shmem_base); ++ ++ if (unlikely(!from_irq) && !(handler_msg->complete & MSG_COMPLETE)) ++ return false; ++ msg.data[0] = c; ++ msg.length = count; ++ ++ /* set 1 to wait rv clear out */ ++ phytium_uart_write(1, pup, REG_CHECK_TX); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ pup->port.icount.tx++; ++ ++ return true; ++ ++} ++ ++static bool phytium_tx_chars(struct phytium_uart_port *pup, bool from_irq) ++{ ++ struct circ_buf *xmit = &pup->port.state->xmit; ++ struct msg msg; ++ int i = 0; ++ int count = TX_DATA_MAXINUM; ++ u16 datasize = 0; ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_DATA, MSG_TX_DATA, 0); ++ ++ if (pup->port.x_char) { ++ if (!phytium_tx_xchar(pup, pup->port.x_char, from_irq)) ++ return true; ++ pup->port.x_char = 0; ++ --count; ++ } ++ ++ if (uart_circ_empty(xmit) || uart_tx_stopped(&pup->port)) { ++ phytium_stop_tx(&pup->port); ++ return false; ++ } ++ ++ if (tx_ring_buffer_is_full(pup)) ++ return false; ++ do { ++ if (count-- == 0) ++ break; ++ datasize++; ++ ++ msg.length = datasize; ++ msg.data[datasize - 1] = xmit->buf[xmit->tail]; ++ ++ pup->port.icount.tx++; ++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ++ } while (!uart_circ_empty(xmit)); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ /* if xmit is empty, break */ ++ if (uart_circ_empty(xmit)) ++ pr_debug("xmit is empty at i=%d\n", i); ++ /* If tx_chars is called by start_tx or xmit ++ * data is full enough to fill msg, don't wakeup ++ * write again. ++ */ ++ if (uart_circ_chars_pending(xmit) <= TX_DATA_MAXINUM) ++ uart_write_wakeup(&pup->port); ++ if (uart_circ_empty(xmit)) { ++ phytium_stop_tx(&pup->port); ++ return false; ++ } ++ return true; ++} ++ ++static void phytium_modem_status(struct phytium_uart_port *pup) ++{ ++ struct msg msg; ++ struct msg *handler_msg; ++ unsigned int status, delta; ++ u16 old_tx_tail; ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_GET, MSG_GET_MODEM, 0); ++ ++ old_tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ handler_msg = ++ (struct msg *)(pup->shmem_base + TX_MSG_SIZE * old_tx_tail); ++ ++ while (!tx_ring_buffer_is_empty(pup)) ++ cpu_relax(); ++ ++ status = handler_msg->data[0]; ++ ++ delta = status ^ pup->old_status; ++ pup->old_status = status; ++ ++ if (!delta) ++ return; ++ ++ if (delta & MODEM_DCD) ++ uart_handle_dcd_change(&pup->port, status & MODEM_DCD); ++ ++ if (delta & MODEM_DSR) ++ pup->port.icount.dsr++; ++ ++ if (delta & MODEM_CTS) ++ uart_handle_cts_change(&pup->port, status & MODEM_CTS); ++ ++ wake_up_interruptible(&pup->port.state->port.delta_msr_wait); ++} ++ ++static irqreturn_t phytium_uart_interrupt(int irq, void *uart_port) ++{ ++ struct phytium_uart_port *pup = uart_port; ++ unsigned long flags; ++ unsigned int status; ++ int handled = 0; ++ ++ spin_lock_irqsave(&pup->port.lock, flags); ++ status = phytium_uart_read(pup, REG_RP_INT_STATE); ++ if (status) { ++ /* clear rx_tail,tx_data_complete interrupts */ ++ phytium_uart_write(status & ~(TX_HEAD_INT | RX_TAIL_INT | ++ PHYT_MSG_DATA_COMPLETED | MODEM_INT), ++ pup, REG_RP_INT_STATE); ++ ++ phytium_uart_write(TX_HEAD_INT | RX_TAIL_INT | ++ PHYT_MSG_DATA_COMPLETED | MODEM_INT, ++ pup, REG_RP_INT_STATE_CLR); ++ ++ if (status & RX_TAIL_INT) ++ phytium_rx_chars(pup); ++ ++ if (status & MODEM_INT) ++ phytium_modem_status(pup); ++ ++ if (status & PHYT_MSG_DATA_COMPLETED) ++ phytium_tx_chars(pup, true); ++ ++ handled = 1; ++ } ++ spin_unlock_irqrestore(&pup->port.lock, flags); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static unsigned int phytium_tx_empty(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ unsigned int status; ++ ++ status = tx_ring_buffer_is_full(pup); ++ return status ? 0 : TIOCSER_TEMT; ++} ++ ++ ++static void phytium_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ struct msg msg; ++ unsigned int status; ++ cmd_subid_type cmd_subid; ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_MCTRL; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ msg.data[3] = (mctrl >> 24) & MSG_DATA_MASK; ++ msg.data[2] = (mctrl >> 16) & MSG_DATA_MASK; ++ msg.data[1] = (mctrl >> 8) & MSG_DATA_MASK; ++ msg.data[0] = (mctrl) & MSG_DATA_MASK; ++ ++ if (port->status & UPSTAT_AUTORTS) { ++ status = 1; ++ msg.data[7] = (status >> 24) & MSG_DATA_MASK; ++ msg.data[6] = (status >> 16) & MSG_DATA_MASK; ++ msg.data[5] = (status >> 8) & MSG_DATA_MASK; ++ msg.data[4] = (status) & MSG_DATA_MASK; ++ } ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++} ++ ++static unsigned int phytium_get_mctrl(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int cr = 0; ++ unsigned int status; ++ struct msg msg; ++ struct msg *handler_msg; ++ u16 old_tx_tail; ++ ++ old_tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_GET, MSG_GET_MODEM, 0); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ handler_msg = ++ (struct msg *)(pup->shmem_base + TX_MSG_SIZE * old_tx_tail); ++ while (!tx_ring_buffer_is_empty(pup)) ++ cpu_relax(); ++ status = handler_msg->data[0]; ++ ++ if (status & MODEM_CTS) ++ cr |= TIOCM_CTS; ++ if (status & MODEM_DSR) ++ cr |= TIOCM_DSR; ++ if (status & MODEM_CAR) ++ cr |= TIOCM_CAR; ++ if (status & MODEM_RNG) ++ cr |= TIOCM_RNG; ++ if (status & MODEM_RTS) ++ cr |= TIOCM_RTS; ++ if (status & MODEM_DTR) ++ cr |= TIOCM_DTR; ++ if (status & MODEM_OUT1) ++ cr |= TIOCM_OUT1; ++ if (status & MODEM_OUT2) ++ cr |= TIOCM_OUT2; ++ ++ return cr; ++} ++ ++static void phytium_start_tx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int int_mask = 0; ++ ++ /* unmask tx_ring_buffer interrupt */ ++ if (phytium_tx_chars(pup, false)) { ++ int_mask = phytium_uart_read(pup, REG_RP_INT_MASK); ++ phytium_uart_write(int_mask & ~PHYT_MSG_DATA_COMPLETED, ++ pup, REG_RP_INT_MASK); ++ } ++} ++ ++static void phytium_stop_rx(struct uart_port *port) ++{ ++ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ struct msg msg; ++ cmd_subid_type cmd_subid; ++ unsigned int int_mask; ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_ERROR_IM; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ /* mask rx tail int */ ++ int_mask = phytium_uart_read(pup, REG_RP_INT_MASK); ++ phytium_uart_write(int_mask | RX_TAIL_INT, pup, REG_RP_INT_MASK); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++} ++ ++static void phytium_throttle_rx(struct uart_port *port) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ ++ phytium_stop_rx(port); ++ ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++ ++static void phytium_enable_ms(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ struct msg msg; ++ cmd_subid_type cmd_subid; ++ ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_MODEM_IM; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ msg.data[0] = 0xf; ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++} ++ ++static void phytium_break_ctl(struct uart_port *port, int break_state) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ struct msg msg; ++ unsigned long flags; ++ unsigned int ctrl = 1; ++ cmd_subid_type cmd_subid; ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_BREAK_EN; ++ ++ cmd_subid = getHexValue(cmd); ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ spin_lock_irqsave(&pup->port.lock, flags); ++ if (break_state == -1) { ++ ++ msg.data[3] = (ctrl >> 24) & MSG_DATA_MASK; ++ msg.data[2] = (ctrl >> 16) & MSG_DATA_MASK; ++ msg.data[1] = (ctrl >> 8) & MSG_DATA_MASK; ++ msg.data[0] = (ctrl) & MSG_DATA_MASK; ++ } ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ spin_unlock_irqrestore(&pup->port.lock, flags); ++ ++} ++ ++static int phytium_hwinit(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ struct msg msg; ++ int retval; ++ u64 uart_clk; ++ unsigned int int_mask; ++ unsigned int status; ++ cmd_subid_type cmd_subid; ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_HWINIT; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ pinctrl_pm_select_default_state(port->dev); ++ ++ retval = clk_prepare_enable(pup->clk); ++ if (retval) ++ return retval; ++ if (has_acpi_companion(pup->port.dev)) { ++ device_property_read_u64(pup->port.dev, "clock-frequency", ++ &uart_clk); ++ if (uart_clk) { ++ if (uart_clk > 100000000 || ('n' == uart_clk)) { ++ dev_err(pup->port.dev, "uartclk get from acpi is error or NULL!\n"); ++ pup->port.uartclk = DEFAULT_CLK; ++ } else ++ pup->port.uartclk = (uint32_t)uart_clk; ++ } else { ++ dev_err(pup->port.dev, "have no acpi clk, use default clk!\n"); ++ pup->port.uartclk = DEFAULT_CLK; ++ } ++ } else ++ pup->port.uartclk = clk_get_rate(pup->clk); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ status = phytium_uart_read(pup, REG_RP_INT_STATE); ++ phytium_uart_write(status & ~RX_TAIL_INT, pup, REG_RP_INT_STATE); ++ phytium_uart_write(RX_TAIL_INT, pup, REG_RP_INT_STATE_CLR); ++ /* unmask rx tail int */ ++ int_mask = phytium_uart_read(pup, REG_RP_INT_MASK); ++ phytium_uart_write(int_mask & ~RX_TAIL_INT, pup, REG_RP_INT_MASK); ++ ++ return 0; ++} ++ ++static int phytium_uart_allocate_irq(struct phytium_uart_port *pup) ++{ ++ if (!pup->port.irq) ++ return -EINVAL; ++ ++ return request_irq(pup->port.irq, phytium_uart_interrupt, ++ IRQF_SHARED, DRV_NAME, pup); ++} ++ ++static void phytium_enable_interrupts(struct phytium_uart_port *pup) ++{ ++ unsigned long flags; ++ unsigned int i; ++ u16 rx_head, rx_tail; ++ unsigned int status; ++ unsigned int int_mask; ++ ++ unsigned int buffer_size = RX_BUFFER_SIZE; ++ ++ spin_lock_irqsave(&pup->port.lock, flags); ++ ++ /* clear out rx-int-status */ ++ status = phytium_uart_read(pup, REG_RP_INT_STATE); ++ phytium_uart_write(status & ~RX_TAIL_INT, pup, REG_RP_INT_STATE); ++ /* when enable int, first empty rx ring buffer */ ++ for (i = 0; i < buffer_size * 2; i++) { ++ if (rx_ring_buffer_is_empty(pup)) ++ break; ++ rx_head = phytium_uart_read(pup, REG_RX_HEAD) ++ & BUFFER_POINTER_MASK; ++ rx_head = (rx_head + 1) % buffer_size; ++ phytium_uart_write(rx_head, pup, REG_RX_HEAD); ++ } ++ ++ /* enable rx_tail int */ ++ rx_tail = phytium_uart_read(pup, REG_RX_TAIL); ++ phytium_uart_write(rx_tail | RX_TAIL_INT_ENABLE, pup, REG_RX_TAIL); ++ ++ /* unmask rx tail int */ ++ int_mask = phytium_uart_read(pup, REG_RP_INT_MASK); ++ phytium_uart_write(int_mask & ~RX_TAIL_INT, pup, REG_RP_INT_MASK); ++ spin_unlock_irqrestore(&pup->port.lock, flags); ++} ++ ++static void phytium_unthrottle_rx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ phytium_enable_interrupts(pup); ++} ++ ++ ++static int phytium_startup(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ struct msg msg; ++ struct msg *handler_msg; ++ cmd_subid_type cmd_subid; ++ int ret = 0; ++ u16 old_tx_tail; ++ ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_STARTUP; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ ret = phytium_hwinit(port); ++ if (ret) ++ goto out; ++ ++ ret = phytium_uart_allocate_irq(pup); ++ if (ret) ++ goto out; ++ ++ spin_lock_irq(&pup->port.lock); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ spin_unlock_irq(&pup->port.lock); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_GET, MSG_GET_MODEM, 0); ++ ++ old_tx_tail = phytium_uart_read(pup, REG_TX_TAIL) & BUFFER_POINTER_MASK; ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ handler_msg = (struct msg *) ++ (pup->shmem_base + TX_MSG_SIZE * old_tx_tail); ++ ++ while (!tx_ring_buffer_is_empty(pup)) ++ cpu_relax(); ++ ++ pup->old_status = handler_msg->data[0]; ++ ++ phytium_enable_interrupts(pup); ++ ++ return 0; ++out: ++ return ret; ++} ++ ++static void phytium_disable_uart(struct phytium_uart_port *pup) ++{ ++ ++ struct msg msg; ++ cmd_subid_type cmd_subid; ++ ++ enum phytuart_set_subid cmd = PHYTUART_MSG_CMD_SET_DISABLE_UART; ++ ++ cmd_subid = getHexValue(cmd); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0); ++ ++ /* set none flow control status */ ++ pup->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); ++ spin_lock_irq(&pup->port.lock); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ spin_unlock_irq(&pup->port.lock); ++ ++} ++ ++static void phytium_disable_interrupts(struct phytium_uart_port *pup) ++{ ++ struct msg msg; ++ ++ /* reset uart */ ++ msg_fill(&msg, UART_MODULE_ID, MSG_DEFAULT, MSG_DEFAULT_SUBID, 0); ++ ++ spin_lock_irq(&pup->port.lock); ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ /* clear all RP INT STATUS */ ++ phytium_uart_write(0, pup, REG_RP_INT_STATE); ++ phytium_uart_write(0xffff, pup, REG_RP_INT_STATE_CLR); ++ spin_unlock_irq(&pup->port.lock); ++} ++ ++static void phytium_shutdown(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ phytium_disable_interrupts(pup); ++ ++ free_irq(pup->port.irq, pup); ++ ++ phytium_disable_uart(pup); ++ ++ /* Shut down the clock producer */ ++ clk_disable_unprepare(pup->clk); ++ ++ /* Optionally let pins go into sleep states */ ++ pinctrl_pm_select_sleep_state(port->dev); ++ ++} ++ ++static void ++phytium_setup_status_masks(struct uart_port *port, struct ktermios *termios) ++{ ++ port->read_status_mask = DATA_OE | CHAR_MASK; ++ ++ if (termios->c_iflag & INPCK) ++ port->read_status_mask |= DATA_FE | DATA_PE; ++ ++ if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) ++ port->read_status_mask |= DATA_BE; ++ ++ /* ++ * Characters to ignore ++ */ ++ port->ignore_status_mask = 0; ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= DATA_FE | DATA_PE; ++ ++ if (termios->c_iflag & IGNBRK) { ++ port->ignore_status_mask |= DATA_BE; ++ /* ++ * If we're ignoring parity and break indicators, ++ * ignore overruns too (for real raw support). ++ */ ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= DATA_OE; ++ } ++ ++ /* ++ * Ignore all characters if CREAD is not set. ++ */ ++ if ((termios->c_cflag & CREAD) == 0) ++ port->ignore_status_mask |= DATA_DUMMY_RX; ++} ++ ++static void ++phytium_set_termios(struct uart_port *port, struct ktermios *termios, ++ struct ktermios *old) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ struct msg msg; ++ u64 uart_clk; ++ unsigned long flags; ++ unsigned int baud, quot; ++ u8 databits = 0; ++ u8 stopbits = 0; ++ u8 parity_en = 0; ++ u8 parodd = 0; ++ u8 cmspar = 0; ++ u8 crtscts = 0; ++ cmd_subid_type cmd_subid1, cmd_subid2; ++ ++ enum phytuart_set_subid cmd1 = PHYTUART_MSG_CMD_SET_BAUD; ++ enum phytuart_set_subid cmd2 = PHYTUART_MSG_CMD_SET_TERMIOS; ++ ++ cmd_subid1 = getHexValue(cmd1); ++ cmd_subid2 = getHexValue(cmd2); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid1, 0); ++ ++ spin_lock_irqsave(&port->lock, flags); ++ /* Ask the core to calculate the divisor for us. */ ++ if (has_acpi_companion(pup->port.dev)) { ++ device_property_read_u64(pup->port.dev, "clock-frequency", ++ &uart_clk); ++ if (uart_clk) { ++ if (uart_clk > 100000000 || ('n' == uart_clk)) { ++ dev_err(pup->port.dev, "uartclk get from acpi is error or NULL!\n"); ++ port->uartclk = DEFAULT_CLK; ++ } else ++ port->uartclk = (uint32_t)uart_clk; ++ } else { ++ dev_err(pup->port.dev, "have no acpi clk, use default clk!\n"); ++ port->uartclk = DEFAULT_CLK; ++ } ++ } ++ baud = uart_get_baud_rate(port, termios, old, 0, ++ port->uartclk/16); ++ dev_info(pup->port.dev, "get baud to set:%d\n", baud); ++ if (baud > port->uartclk/16) ++ quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); ++ else ++ quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud); ++ ++ /* set baud */ ++ msg.data[7] = (port->uartclk >> 24) & MSG_DATA_MASK; ++ msg.data[6] = (port->uartclk >> 16) & MSG_DATA_MASK; ++ msg.data[5] = (port->uartclk >> 8) & MSG_DATA_MASK; ++ msg.data[4] = (port->uartclk) & MSG_DATA_MASK; ++ msg.data[3] = (baud >> 24) & MSG_DATA_MASK; ++ msg.data[2] = (baud >> 16) & MSG_DATA_MASK; ++ msg.data[1] = (baud >> 8) & MSG_DATA_MASK; ++ msg.data[0] = (baud) & MSG_DATA_MASK; ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ switch (termios->c_cflag & CSIZE) { ++ case CS5: ++ databits = 0; ++ break; ++ case CS6: ++ databits = 1; ++ break; ++ case CS7: ++ databits = 2; ++ break; ++ default: /* CS8 */ ++ databits = 3; ++ break; ++ } ++ ++ if (termios->c_cflag & CSTOPB) ++ stopbits = 1; ++ if (termios->c_cflag & PARENB) { ++ parity_en = 1; ++ if (!(termios->c_cflag & PARODD)) ++ parodd = 0; ++ if (termios->c_cflag & CMSPAR) ++ cmspar = 1; ++ ++ ++ } ++ ++ /* ++ * Update the per-port timeout. ++ */ ++ ++ uart_update_timeout(port, termios->c_cflag, baud); ++ ++ phytium_setup_status_masks(port, termios); ++ ++ if (UART_ENABLE_MS(port, termios->c_cflag)) ++ phytium_enable_ms(port); ++ ++ if (termios->c_cflag & CRTSCTS) { ++ crtscts = 1; ++ port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; ++ } else { ++ crtscts = 0; ++ port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); ++ } ++ ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid2, 0); ++ ++ msg.data[0] = databits & MSG_DATA_MASK; ++ msg.data[1] = stopbits & MSG_DATA_MASK; ++ msg.data[2] = parity_en & MSG_DATA_MASK; ++ msg.data[3] = parodd & MSG_DATA_MASK; ++ msg.data[4] = cmspar & MSG_DATA_MASK; ++ msg.data[5] = crtscts & MSG_DATA_MASK; ++ ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++static const char *phytium_type(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ return pup->port.type == PORT_PHYTIUM ? pup->type : NULL; ++} ++ ++static void phytium_config_port(struct uart_port *port, int flags) ++{ ++ if (flags & UART_CONFIG_TYPE) ++ port->type = PORT_PHYTIUM; ++} ++ ++static int phytium_verify_port(struct uart_port *port, ++ struct serial_struct *ser) ++{ ++ int ret = 0; ++ ++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_PHYTIUM) ++ ret = -EINVAL; ++ if (ser->irq < 0 || ser->irq >= nr_irqs) ++ ret = -EINVAL; ++ if (ser->baud_base < 9600) ++ ret = -EINVAL; ++ if (port->mapbase != (unsigned long) ser->iomem_base) ++ ret = -EINVAL; ++ return ret; ++} ++ ++static const struct uart_ops phytium_uart_ops = { ++ .tx_empty = phytium_tx_empty, ++ .set_mctrl = phytium_set_mctrl, ++ .get_mctrl = phytium_get_mctrl, ++ .stop_tx = phytium_stop_tx, ++ .start_tx = phytium_start_tx, ++ .stop_rx = phytium_stop_rx, ++ .throttle = phytium_throttle_rx, ++ .unthrottle = phytium_unthrottle_rx, ++ .enable_ms = phytium_enable_ms, ++ .break_ctl = phytium_break_ctl, ++ .startup = phytium_startup, ++ .shutdown = phytium_shutdown, ++ .set_termios = phytium_set_termios, ++ .type = phytium_type, ++ .config_port = phytium_config_port, ++ .verify_port = phytium_verify_port, ++}; ++ ++static struct phytium_uart_port *uart_ports[UART_NR]; ++ ++static struct uart_driver phytium_uart = { ++ .owner = THIS_MODULE, ++ .driver_name = DRV_NAME, ++ .dev_name = "ttyVS", ++ .nr = UART_NR, ++}; ++ ++static void phytium_unregister_port(struct phytium_uart_port *pup) ++{ ++ int i; ++ bool busy = false; ++ ++ for (i = 0; i < ARRAY_SIZE(uart_ports); i++) { ++ if (uart_ports[i] == pup) ++ uart_ports[i] = NULL; ++ else if (uart_ports[i]) ++ busy = true; ++ } ++ ++ if (!busy) ++ uart_unregister_driver(&phytium_uart); ++} ++ ++static int phytium_find_free_port(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(uart_ports); i++) ++ if (uart_ports[i] == NULL) ++ return i; ++ ++ return -EBUSY; ++} ++ ++static int phytium_register_port(struct phytium_uart_port *pup) ++{ ++ struct msg msg; ++ int rc, i; ++ ++ /* mask TX_HEAD_INT at the beginning, because now we are ++ * unable to deal with it yet ++ */ ++ phytium_uart_write(TX_HEAD_INT, pup, REG_RP_INT_MASK); ++ ++ msg_fill(&msg, UART_MODULE_ID, MSG_DEFAULT, MSG_DEFAULT, 0); ++ PHYT_MSG_INSERT(pup, &msg); ++ ++ /* clear all redundant RP INT STATUS at the beginning */ ++ phytium_uart_write(0, pup, REG_RP_INT_STATE); ++ phytium_uart_write(0xffff, pup, REG_RP_INT_STATE_CLR); ++ if (!phytium_uart.state) { ++ rc = uart_register_driver(&phytium_uart); ++ if (rc < 0) { ++ dev_err(pup->port.dev, ++ "Failed to register Phytium platform UART driver\n"); ++ for (i = 0; i < ARRAY_SIZE(uart_ports); i++) ++ if (uart_ports[i] == pup) ++ uart_ports[i] = NULL; ++ return rc; ++ } ++ } ++ ++ rc = uart_add_one_port(&phytium_uart, &pup->port); ++ if (rc) ++ phytium_unregister_port(pup); ++ ++ return rc; ++} ++ ++#if defined(SERIAL_PHYTIUM_V2_DEBUG) ++static int phytium_uart_enable_debug(struct phytium_uart_port *pup, ++ bool new_enable_flag) ++{ ++ u32 dbg_regval; ++ static bool old_enable_flag; ++ ++ if (old_enable_flag == new_enable_flag) { ++ pr_warn("PHYUART:set enable debug with repeative operation.\n"); ++ return -1; ++ } ++ old_enable_flag = new_enable_flag; ++ dbg_regval = phytium_uart_read(pup, PHYUART_DBG_REG); ++ pr_info("PHYUART: %s debug_regval %x\n", __func__, dbg_regval); ++ if (!old_enable_flag && (dbg_regval & PHYUART_DBG_ENABLE_MASK)) ++ dbg_regval &= ~PHYUART_DBG_ENABLE_MASK; ++ else if (dbg_regval && !(dbg_regval & PHYUART_DBG_ENABLE_MASK)) ++ dbg_regval |= PHYUART_DBG_ENABLE_MASK; ++ ++ pr_info("final PHYUART: %s debug_regval %x\n", __func__, dbg_regval); ++ phytium_uart_write(dbg_regval, pup, PHYUART_DBG_REG); ++ return 0; ++} ++ ++static int phytium_uart_enable_heartbeat(struct phytium_uart_port *pup, ++ bool new_heartbeat_flag) ++{ ++ u32 dbg_regval; ++ static bool old_heartbeat_flag; ++ ++ if (old_heartbeat_flag == new_heartbeat_flag) { ++ pr_warn("PHYUART:set heartbeat with repeative operation.\n"); ++ return -1; ++ } ++ old_heartbeat_flag = new_heartbeat_flag; ++ dbg_regval = phytium_uart_read(pup, PHYUART_DBG_REG); ++ pr_info("PHYUART: %s dbg_regval %x\n", __func__, dbg_regval); ++ if (!old_heartbeat_flag && (dbg_regval & PHYUART_DBG_HEARTBEAT_MASK)) ++ dbg_regval &= ~PHYUART_DBG_HEARTBEAT_MASK; ++ else if (dbg_regval && !(dbg_regval & PHYUART_DBG_HEARTBEAT_MASK)) ++ dbg_regval |= PHYUART_DBG_HEARTBEAT_MASK ++ | PHYUART_DBG_HEARTBEAT_ENABLE_MASK; ++ ++ pr_info("final PHYUART: %s dbg_regval %x\n", __func__, dbg_regval); ++ phytium_uart_write(dbg_regval, pup, PHYUART_DBG_REG); ++ return 0; ++} ++ ++static void alive_timer_routine(struct timer_list *tlist) ++{ ++ struct phytium_uart_port *pup; ++ u32 dbg_regval; ++ ++ pup = from_timer(pup, tlist, alive_timer); ++ if (!pup) { ++ pr_err("PHYUART: get uart port error.\n"); ++ return; ++ } ++ ++ dbg_regval = phytium_uart_read(pup, PHYUART_DBG_REG); ++ pr_debug("PHYUART: %s debug_regval 0x%x\n", __func__, dbg_regval); ++ phytium_uart_write(dbg_regval | PHYUART_DBG_HEARTBEAT_MASK, ++ pup, PHYUART_DBG_REG); ++ mod_timer(&pup->alive_timer, jiffies + msecs_to_jiffies(5000)); ++} ++ ++static ssize_t debug_enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct phytium_uart_port *pup = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", pup->debug_enable_flag); ++} ++ ++static ssize_t debug_enable_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct phytium_uart_port *pup = dev_get_drvdata(dev); ++ int enable; ++ int ret; ++ ++ ret = sscanf(buf, "%d\n", &enable); ++ if (ret == 0) { ++ ret = -EINVAL; ++ return ret; ++ } ++ pup->debug_enable_flag = enable; ++ phytium_uart_enable_debug(pup, pup->debug_enable_flag); ++ return count; ++} ++ ++static ssize_t heartbeat_enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct phytium_uart_port *pup = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", pup->heartbeat_enable_flag); ++} ++ ++static ssize_t heartbeat_enable_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct phytium_uart_port *pup = dev_get_drvdata(dev); ++ int heartbeat_enable; ++ int ret; ++ ++ ret = sscanf(buf, "%d\n", &heartbeat_enable); ++ if (ret == 0) { ++ ret = -EINVAL; ++ return ret; ++ } ++ pup->heartbeat_enable_flag = heartbeat_enable; ++ phytium_uart_enable_heartbeat(pup, pup->heartbeat_enable_flag); ++ return count; ++} ++static DEVICE_ATTR_RW(debug_enable); ++static DEVICE_ATTR_RW(heartbeat_enable); ++#endif ++static int phytium_uart_probe(struct platform_device *pdev) ++{ ++ struct phytium_uart_port *pup; ++ struct resource *res_rf, *res_sm; ++ int portnr, ret; ++ u64 uart_clk; ++ ++ portnr = phytium_find_free_port(); ++ if (portnr < 0) ++ return portnr; ++ ++ pup = devm_kzalloc(&pdev->dev, sizeof(struct phytium_uart_port), ++ GFP_KERNEL); ++ if (!pup) ++ return -ENOMEM; ++ ++ if (pdev->dev.of_node) { ++ pup->clk = devm_clk_get(&pdev->dev, "uartclk"); ++ if (IS_ERR(pup->clk)) { ++ dev_err(&pdev->dev, "Device clock not found.\n"); ++ ret = PTR_ERR(pup->clk); ++ goto free; ++ } ++ } ++ ++ res_rf = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res_rf) { ++ dev_err(&pdev->dev, "UNABLE TO GET REGFILE RESOURCE!\n"); ++ goto free; ++ } ++ ++ res_sm = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res_sm) { ++ dev_err(&pdev->dev, "UNABLE TO GET SHMEM RESOURCE!\n"); ++ goto free; ++ } ++ ++ pup->shmem_base = devm_ioremap_resource(&pdev->dev, res_sm); ++ ++ pup->dev = &pdev->dev; ++ pup->port.irq = platform_get_irq(pdev, 0); ++ ++ ret = clk_prepare_enable(pup->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "PHYUART:clk_prepare_enable error.\n"); ++ goto free; ++ } ++ ++ pup->port.dev = &pdev->dev; ++ if (has_acpi_companion(pup->port.dev)) { ++ device_property_read_u64(pup->port.dev, "clock-frequency", ++ &uart_clk); ++ if (uart_clk) { ++ if (uart_clk > 100000000 || ('n' == uart_clk)) { ++ dev_err(pup->port.dev, "uartclk get from acpi is error or NULL!\n"); ++ pup->port.uartclk = DEFAULT_CLK; ++ } else ++ pup->port.uartclk = (uint32_t)uart_clk; ++ } else { ++ dev_err(pup->port.dev, "have no acpi clk, use default clk!\n"); ++ pup->port.uartclk = DEFAULT_CLK; ++ } ++ } else ++ pup->port.uartclk = clk_get_rate(pup->clk); ++ pup->port.mapbase = res_rf->start; ++ pup->port.membase = devm_ioremap_resource(&pdev->dev, res_rf); ++ pup->port.iotype = UPIO_MEM32; ++ pup->port.ops = &phytium_uart_ops; ++ pup->port.dev = &pdev->dev; ++ pup->port.fifosize = UART_FIFOSIZE; ++ pup->port.flags = UPF_BOOT_AUTOCONF; ++ pup->port.line = portnr; ++ uart_ports[portnr] = pup; ++ pup->old_cr = 0; ++ pup->m_buf_empty = true; ++ snprintf(pup->type, sizeof(pup->type), "phytium,uart-v2"); ++#if defined(SERIAL_PHYTIUM_V2_DEBUG) ++ pup->debug_enable_flag = false; ++ pup->heartbeat_enable_flag = false; ++ ++ phytium_uart_enable_heartbeat(pup, true); ++ phytium_uart_enable_debug(pup, true); ++ ++ pup->alive_timer.expires = jiffies + msecs_to_jiffies(5000); ++ timer_setup(&pup->alive_timer, alive_timer_routine, 0); ++ add_timer(&pup->alive_timer); ++ ret = device_create_file(&pdev->dev, ++ &dev_attr_debug_enable); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "PHYUART: device_create_debug file error.\n"); ++ goto debug_enable_free; ++ } ++ ret = device_create_file(&pdev->dev, ++ &dev_attr_heartbeat_enable); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "PHYUART: device_create_heartbeat file error.\n"); ++ goto heartbeat_enable_free; ++ } ++#endif ++ platform_set_drvdata(pdev, pup); ++ return phytium_register_port(pup); ++ ++#if defined(SERIAL_PHYTIUM_V2_DEBUG) ++heartbeat_enable_free: ++ device_remove_file(pup->dev, &dev_attr_heartbeat_enable); ++debug_enable_free: ++ device_remove_file(pup->dev, &dev_attr_debug_enable); ++#endif ++free: ++ kfree(pup); ++ return -1; ++} ++ ++static int phytium_uart_remove(struct platform_device *pdev) ++{ ++ struct phytium_uart_port *pup = platform_get_drvdata(pdev); ++ ++ uart_remove_one_port(&phytium_uart, &pup->port); ++ ++ phytium_unregister_port(pup); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int phytium_uart_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct phytium_uart_port *pup = platform_get_drvdata(pdev); ++ ++ if (pup) ++ uart_suspend_port(&phytium_uart, &pup->port); ++ ++ return 0; ++} ++ ++static int phytium_uart_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct phytium_uart_port *pup = platform_get_drvdata(pdev); ++ ++ if (pup) ++ uart_resume_port(&phytium_uart, &pup->port); ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(phytium_dev_pm_ops, ++ phytium_uart_suspend, phytium_uart_resume); ++ ++/* Match table for OF platform binding */ ++static const struct of_device_id phytium_uart_of_ids[] = { ++ { .compatible = "phytium,uart-2.0", }, ++ { /* end of list */ }, ++}; ++MODULE_DEVICE_TABLE(of, phytium_uart_of_ids); ++ ++static const struct acpi_device_id __maybe_unused phytium_uart_acpi_match[] = { ++ { "PHYT0055", 0 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(acpi, phytium_uart_acpi_match); ++ ++static struct platform_driver phytium_uart_driver = { ++ .probe = phytium_uart_probe, ++ .remove = phytium_uart_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = phytium_uart_of_ids, ++ .acpi_match_table = ACPI_PTR(phytium_uart_acpi_match), ++ .pm = &phytium_dev_pm_ops, ++ }, ++}; ++ ++static int __init phytium_uart_init(void) ++{ ++ pr_info("Serial: Phytium uart v2 driver\n"); ++ return platform_driver_register(&phytium_uart_driver); ++} ++ ++static void __exit phytium_uart_exit(void) ++{ ++ platform_driver_unregister(&phytium_uart_driver); ++} ++arch_initcall(phytium_uart_init); ++module_exit(phytium_uart_exit); ++ ++MODULE_AUTHOR("Lan Hengyu "); ++MODULE_DESCRIPTION("Phytium serial port driver for uart v2"); ++MODULE_VERSION(PHYT_UART_DRV_VER); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/tty/serial/phytium-uart-v2.h b/drivers/tty/serial/phytium-uart-v2.h +new file mode 100644 +index 000000000000..90e848783063 +--- /dev/null ++++ b/drivers/tty/serial/phytium-uart-v2.h +@@ -0,0 +1,159 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (c) 2020-2025, Phytium Technology, Co., Ltd. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_NAME "ttyVS" ++#define MSG_COMPLETE 0x1 ++#define UART_NR 14 ++ ++#define TX_DATA_MAXINUM 120 ++#define RX_DATA_MAXINUM ((TX_DATA_MAXINUM / 2) + 1) ++ ++#define DATA_OE (1 << 11) ++#define DATA_BE (1 << 10) ++#define DATA_PE (1 << 9) ++#define DATA_FE (1 << 8) ++#define DATA_ERROR (DATA_OE|DATA_BE|DATA_PE|DATA_FE) ++#define DATA_DUMMY_RX (1 << 16) ++ ++#define REG_TX_HEAD 0x0 /* tx_ring_buffer head pointer reg */ ++#define REG_TX_TAIL 0x4 /* tx_ring_buffer tail pointer reg */ ++#define REG_RX_HEAD 0x8 /* rx_ring_buffer tail pointer reg */ ++#define REG_RX_TAIL 0xc /* rx_ring_buffer tail pointer reg */ ++#define REG_PHYT_INT_STATE 0x24 ++#define REG_RP_INT_STATE 0x2c ++#define REG_RP_INT_STATE_CLR 0x74 ++#define REG_PHYT_INT_MASK 0x20 ++#define REG_RP_INT_MASK 0x28 ++#define REG_FAKE_DR 0x30 ++#define REG_FAKE_FR 0x34 ++#define REG_CHECK_TX 0x4c ++ ++#define MODEM_CTS 0x1 ++#define MODEM_DSR 0x2 ++#define MODEM_DCD 0x004 ++#define MODEM_CAR MODEM_DCD ++#define MODEM_RNG 0x8 ++#define MODEM_RTS 0x10 ++#define MODEM_DTR 0x20 ++#define MODEM_OUT1 0x40 ++#define MODEM_OUT2 0x80 ++ ++#define TX_HEAD_INT 0x1 ++#define RX_TAIL_INT 0x2 ++#define PHYT_INT_TRIGGER_BIT 0x10 ++#define PHYT_MSG_DATA_COMPLETED 0x10 ++#define MODEM_INT 0x20 ++ ++#define UART_MODULE_ID 0x1 ++#define MSG_DEFAULT 0x0 ++#define MSG_DEFAULT_SUBID 0x10 ++#define MSG_SET 0x1 ++#define MSG_GET 0x2 ++#define MSG_DATA 0x3 ++#define MSG_GET_MODEM 0x3 ++#define MSG_GET_RX_EMPTY 0x4 ++#define MSG_TX_DATA 0x0 ++#define RX_TAIL_INT_ENABLE 0x10000 ++#define MSG_DATA_MASK 0xff ++#define BUFFER_POINTER_MASK 0xffff ++#define CHAR_MASK 255 ++ ++#define TX_BUFFER_SIZE 8 ++#define RX_BUFFER_SIZE 8 ++#define BUFFER_SIZE 20 ++#define UART_FIFOSIZE 64 ++#define TX_MSG_SIZE 0x80 ++#define RX_MSG_SIZE 0x80 ++#define RX_CHARS_MAX 28 ++ ++/* uart debug mechanism */ ++#define PHYUART_DBG_REG 0x58 ++/* uart debug register mask bit */ ++#define PHYUART_DBG_ENABLE_MASK 0x1 ++#define PHYUART_DBG_HEARTBEAT_ENABLE_MASK (0x1 << 1) ++#define PHYUART_DBG_HEARTBEAT_MASK (0x1 << 2) ++#define PHYUART_DBG_LOG_EXIST_MASK (0x1 << 3) ++#define PHYUART_DBG_SIZE_MASK (0xf << 4) ++#define PHYUART_DBG_ADDR_MASK (0x3fff << 8) ++ ++/* enum all type-set subid */ ++enum phytuart_set_subid { ++ /* enable/disable */ ++ PHYTUART_MSG_CMD_SET_DEVICE_EN = 0x0, ++ /* set baud */ ++ PHYTUART_MSG_CMD_SET_BAUD, ++ /* set trans bit width 0: 5,1: 6,2: 7,3:8 */ ++ PHYTUART_MSG_CMD_SET_DATABIT, ++ /* set stop bit,0:1 bit, 1: 2bit */ ++ PHYTUART_MSG_CMD_SET_STOPBIT, ++ /* set parity enable, 0:DISABLE, 1:ENABLE */ ++ PHYTUART_MSG_CMD_SET_PARITY_EN, ++ /* set parity bit, 0:ODD, 1: EVEN */ ++ PHYTUART_MSG_CMD_SET_PARITY_EVEN_SET, ++ /* set 0/1 parity enable */ ++ PHYTUART_MSG_CMD_SET_PARITY_STICK_SET, ++ /* set break signal,0:no break 1:send break */ ++ PHYTUART_MSG_CMD_SET_BREAK_EN, ++ /* set RX en, 0:disable, single byte, 1:enable,*/ ++ PHYTUART_MSG_CMD_SET_RX_BUFFER_EN, ++ /* set TX en, 0:disable,single byte, 1:enable */ ++ PHYTUART_MSG_CMD_SET_TX_BUFFER_EN, ++ /* set TX enable, 0:disable, 1:enable */ ++ PHYTUART_MSG_CMD_SET_TX_EN, ++ /* set RX enable, 0:disable, 1:enable */ ++ PHYTUART_MSG_CMD_SET_RX_EN, ++ /* set loop enable, 0:disable, 1:enable */ ++ PHYTUART_MSG_CMD_SET_LOOP_EN, ++ PHYTUART_MSG_CMD_SET_RTS_EN, ++ PHYTUART_MSG_CMD_SET_CTS_EN, ++ PHYTUART_MSG_CMD_SET_DTR_SET, ++ PHYTUART_MSG_CMD_SET_RTS_SET, ++ PHYTUART_MSG_CMD_SET_DTE_DCD_SET, ++ PHYTUART_MSG_CMD_SET_DTE_RI_SET, ++ PHYTUART_MSG_CMD_SET_RX_IM, ++ PHYTUART_MSG_CMD_SET_TX_IM, ++ PHYTUART_MSG_CMD_SET_ERROR_IM, ++ ++ PHYTUART_MSG_CMD_SET_MODEM_IM, ++ PHYTUART_MSG_CMD_SET_STARTUP, ++ PHYTUART_MSG_CMD_SET_HWINIT, ++ PHYTUART_MSG_CMD_SET_MCTRL, ++ PHYTUART_MSG_CMD_SET_TERMIOS, ++ PHYTUART_MSG_CMD_SET_DISABLE_UART, ++}; ++ ++/* for trans subid to hex */ ++uint8_t getHexValue(enum phytuart_set_subid cmd) ++{ ++ return (uint8_t)cmd; ++} +diff --git a/drivers/tty/serial/phytium-uart.c b/drivers/tty/serial/phytium-uart.c +new file mode 100644 +index 000000000000..928126888c92 +--- /dev/null ++++ b/drivers/tty/serial/phytium-uart.c +@@ -0,0 +1,922 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Phytium PCI UART controller ++ * ++ * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_NAME "phytium_uart" ++ ++#define REG_DR 0x00 ++#define REG_FR 0x18 ++#define REG_IBRD 0x24 ++#define REG_FBRD 0x28 ++#define REG_LCRH_RX 0x2c ++#define REG_LCRH_TX 0x2c ++#define REG_CR 0x30 ++#define REG_IFLS 0x34 ++#define REG_IMSC 0x38 ++#define REG_RIS 0x3c ++#define REG_MIS 0x40 ++#define REG_ICR 0x44 ++ ++#define REG_DR_OE (1 << 11) ++#define REG_DR_BE (1 << 10) ++#define REG_DR_PE (1 << 9) ++#define REG_DR_FE (1 << 8) ++ ++#define REG_LCRH_SPS 0x80 ++#define REG_LCRH_WLEN_8 0x60 ++#define REG_LCRH_WLEN_7 0x40 ++#define REG_LCRH_WLEN_6 0x20 ++#define REG_LCRH_WLEN_5 0x00 ++#define REG_LCRH_FEN 0x10 ++#define REG_LCRH_STP2 0x08 ++#define REG_LCRH_EPS 0x04 ++#define REG_LCRH_PEN 0x02 ++#define REG_LCRH_BRK 0x01 ++ ++#define REG_FR_RI 0x100 ++#define REG_FR_TXFE 0x080 ++#define REG_FR_RXFF 0x040 ++#define REG_FR_TXFF 0x020 ++#define REG_FR_RXFE 0x010 ++#define REG_FR_BUSY 0x008 ++#define REG_FR_DCD 0x004 ++#define REG_FR_DSR 0x002 ++#define REG_FR_CTS 0x001 ++#define REG_FR_TMSK (REG_FR_TXFF + REG_FR_BUSY) ++ ++#define REG_CR_CTSEN 0x8000 /* CTS hardware flow control */ ++#define REG_CR_RTSEN 0x4000 /* RTS hardware flow control */ ++#define REG_CR_OUT2 0x2000 /* OUT2 */ ++#define REG_CR_OUT1 0x1000 /* OUT1 */ ++#define REG_CR_RTS 0x0800 /* RTS */ ++#define REG_CR_DTR 0x0400 /* DTR */ ++#define REG_CR_RXE 0x0200 /* receive enable */ ++#define REG_CR_TXE 0x0100 /* transmit enable */ ++#define REG_CR_LBE 0x0080 /* loopback enable */ ++#define REG_CR_RTIE 0x0040 ++#define REG_CR_TIE 0x0020 ++#define REG_CR_RIE 0x0010 ++#define REG_CR_MSIE 0x0008 ++#define REG_CR_IIRLP 0x0004 /* SIR low power mode */ ++#define REG_CR_SIREN 0x0002 /* SIR enable */ ++#define REG_CR_UARTEN 0x0001 /* UART enable */ ++ ++#define REG_IFLS_RX1_8 (0 << 3) ++#define REG_IFLS_RX2_8 (1 << 3) ++#define REG_IFLS_RX4_8 (2 << 3) ++#define REG_IFLS_RX6_8 (3 << 3) ++#define REG_IFLS_RX7_8 (4 << 3) ++#define REG_IFLS_TX1_8 (0 << 0) ++#define REG_IFLS_TX2_8 (1 << 0) ++#define REG_IFLS_TX4_8 (2 << 0) ++#define REG_IFLS_TX6_8 (3 << 0) ++ ++#define REG_IMSC_OEIM (1 << 10) /* overrun error interrupt mask */ ++#define REG_IMSC_BEIM (1 << 9) /* break error interrupt mask */ ++#define REG_IMSC_PEIM (1 << 8) /* parity error interrupt mask */ ++#define REG_IMSC_FEIM (1 << 7) /* framing error interrupt mask */ ++#define REG_IMSC_RTIM (1 << 6) /* receive timeout interrupt mask */ ++#define REG_IMSC_TXIM (1 << 5) /* transmit interrupt mask */ ++#define REG_IMSC_RXIM (1 << 4) /* receive interrupt mask */ ++#define REG_IMSC_DSRMIM (1 << 3) /* DSR interrupt mask */ ++#define REG_IMSC_DCDMIM (1 << 2) /* DCD interrupt mask */ ++#define REG_IMSC_CTSMIM (1 << 1) /* CTS interrupt mask */ ++#define REG_IMSC_RIMIM (1 << 0) /* RI interrupt mask */ ++ ++#define REG_ICR_OEIS (1 << 10) /* overrun error interrupt status */ ++#define REG_ICR_BEIS (1 << 9) /* break error interrupt status */ ++#define REG_ICR_PEIS (1 << 8) /* parity error interrupt status */ ++#define REG_ICR_FEIS (1 << 7) /* framing error interrupt status */ ++#define REG_ICR_RTIS (1 << 6) /* receive timeout interrupt status */ ++#define REG_ICR_TXIS (1 << 5) /* transmit interrupt status */ ++#define REG_ICR_RXIS (1 << 4) /* receive interrupt status */ ++#define REG_ICR_DSRMIS (1 << 3) /* DSR interrupt status */ ++#define REG_ICR_DCDMIS (1 << 2) /* DCD interrupt status */ ++#define REG_ICR_CTSMIS (1 << 1) /* CTS interrupt status */ ++#define REG_ICR_RIMIS (1 << 0) /* RI interrupt status */ ++ ++#define UART_NR 12 ++ ++#define UART_DR_ERROR (REG_DR_OE|REG_DR_BE|REG_DR_PE|REG_DR_FE) ++#define UART_DUMMY_DR_RX (1 << 16) ++ ++#define DEFAULT_UARTCLK 48000000 /* 48 MHz */ ++ ++/* ++ * We wrap our port structure around the generic uart_port. ++ */ ++struct phytium_uart_port { ++ struct uart_port port; ++ unsigned int im; /* interrupt mask */ ++ unsigned int old_status; ++ unsigned int old_cr; /* state during shutdown */ ++ char type[12]; ++}; ++ ++static unsigned int phytium_uart_read(const struct phytium_uart_port *pup, ++ unsigned int reg) ++{ ++ void __iomem *addr = pup->port.membase + reg; ++ ++ return readl_relaxed(addr); ++} ++ ++static void phytium_uart_write(unsigned int val, const struct phytium_uart_port *pup, ++ unsigned int reg) ++{ ++ void __iomem *addr = pup->port.membase + reg; ++ ++ writel_relaxed(val, addr); ++} ++ ++static int phytium_fifo_to_tty(struct phytium_uart_port *pup) ++{ ++ u16 status; ++ unsigned int ch, flag, fifotaken; ++ ++ for (fifotaken = 0; fifotaken < 256; fifotaken++) { ++ status = phytium_uart_read(pup, REG_FR); ++ if (status & REG_FR_RXFE) ++ break; ++ ++ /* Take chars from the FIFO and update status */ ++ ch = phytium_uart_read(pup, REG_DR) | UART_DUMMY_DR_RX; ++ flag = TTY_NORMAL; ++ pup->port.icount.rx++; ++ ++ if (unlikely(ch & UART_DR_ERROR)) { ++ if (ch & REG_DR_BE) { ++ ch &= ~(REG_DR_FE | REG_DR_PE); ++ pup->port.icount.brk++; ++ if (uart_handle_break(&pup->port)) ++ continue; ++ } else if (ch & REG_DR_PE) ++ pup->port.icount.parity++; ++ else if (ch & REG_DR_FE) ++ pup->port.icount.frame++; ++ if (ch & REG_DR_OE) ++ pup->port.icount.overrun++; ++ ++ ch &= pup->port.read_status_mask; ++ ++ if (ch & REG_DR_BE) ++ flag = TTY_BREAK; ++ else if (ch & REG_DR_PE) ++ flag = TTY_PARITY; ++ else if (ch & REG_DR_FE) ++ flag = TTY_FRAME; ++ } ++ ++ if (uart_handle_sysrq_char(&pup->port, ch & 255)) ++ continue; ++ ++ uart_insert_char(&pup->port, ch, REG_DR_OE, ch, flag); ++ } ++ ++ return fifotaken; ++} ++ ++static void phytium_rx_chars(struct phytium_uart_port *pup) ++__releases(&pup->port.lock) ++__acquires(&pup->port.lock) ++{ ++ phytium_fifo_to_tty(pup); ++ ++ spin_unlock(&pup->port.lock); ++ tty_flip_buffer_push(&pup->port.state->port); ++ spin_lock(&pup->port.lock); ++} ++ ++static void phytium_stop_tx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ pup->im &= ~REG_IMSC_TXIM; ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++} ++ ++static bool phytium_tx_char(struct phytium_uart_port *pup, unsigned char c, ++ bool from_irq) ++{ ++ ++ if (unlikely(!from_irq) && ++ phytium_uart_read(pup, REG_FR) & REG_FR_TXFF) ++ return false; /* unable to transmit character */ ++ ++ phytium_uart_write(c, pup, REG_DR); ++ pup->port.icount.tx++; ++ ++ return true; ++} ++ ++static bool phytium_tx_chars(struct phytium_uart_port *pup, bool from_irq) ++{ ++ struct circ_buf *xmit = &pup->port.state->xmit; ++ int count = pup->port.fifosize >> 1; ++ ++ if (pup->port.x_char) { ++ if (!phytium_tx_char(pup, pup->port.x_char, from_irq)) ++ return true; ++ pup->port.x_char = 0; ++ --count; ++ } ++ if (uart_circ_empty(xmit) || uart_tx_stopped(&pup->port)) { ++ phytium_stop_tx(&pup->port); ++ return false; ++ } ++ ++ do { ++ if (likely(from_irq) && count-- == 0) ++ break; ++ ++ if (!phytium_tx_char(pup, xmit->buf[xmit->tail], from_irq)) ++ break; ++ ++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ++ } while (!uart_circ_empty(xmit)); ++ ++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ uart_write_wakeup(&pup->port); ++ ++ if (uart_circ_empty(xmit)) { ++ phytium_stop_tx(&pup->port); ++ return false; ++ } ++ return true; ++} ++ ++static void phytium_modem_status(struct phytium_uart_port *pup) ++{ ++ unsigned int status, delta; ++ ++ status = phytium_uart_read(pup, REG_FR) & (REG_FR_DCD|REG_FR_DSR|REG_FR_CTS); ++ ++ delta = status ^ pup->old_status; ++ pup->old_status = status; ++ ++ if (!delta) ++ return; ++ ++ if (delta & REG_FR_DCD) ++ uart_handle_dcd_change(&pup->port, status & REG_FR_DCD); ++ ++ if (delta & REG_FR_DSR) ++ pup->port.icount.dsr++; ++ ++ if (delta & REG_FR_CTS) ++ uart_handle_cts_change(&pup->port, status & REG_FR_CTS); ++ ++ wake_up_interruptible(&pup->port.state->port.delta_msr_wait); ++} ++ ++static irqreturn_t phytium_uart_interrupt(int irq, void *dev_id) ++{ ++ struct phytium_uart_port *pup = dev_id; ++ unsigned long flags; ++ unsigned int status, pass_counter = 256; ++ int handled = 0; ++ ++ spin_lock_irqsave(&pup->port.lock, flags); ++ status = phytium_uart_read(pup, REG_RIS) & pup->im; ++ if (status) { ++ do { ++ phytium_uart_write(status & ~(REG_ICR_TXIS|REG_ICR_RTIS|REG_ICR_RXIS), ++ pup, REG_ICR); ++ ++ if (status & (REG_ICR_RTIS|REG_ICR_RXIS)) ++ phytium_rx_chars(pup); ++ ++ if (status & (REG_ICR_DSRMIS|REG_ICR_DCDMIS| ++ REG_ICR_CTSMIS|REG_ICR_RIMIS)) ++ phytium_modem_status(pup); ++ if (status & REG_ICR_TXIS) ++ phytium_tx_chars(pup, true); ++ ++ if (pass_counter-- == 0) ++ break; ++ ++ status = phytium_uart_read(pup, REG_RIS) & pup->im; ++ } while (status != 0); ++ handled = 1; ++ } ++ spin_unlock_irqrestore(&pup->port.lock, flags); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static unsigned int phytium_tx_empty(struct uart_port *port) ++{ ++ unsigned int status; ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ status = phytium_uart_read(pup, REG_FR) & (REG_FR_BUSY | REG_FR_TXFF); ++ ++ return status ? 0 : TIOCSER_TEMT; ++} ++ ++static void phytium_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int cr; ++ ++ cr = phytium_uart_read(pup, REG_CR); ++ ++#define TIOCMBIT(tiocmbit, uartbit) \ ++ do { \ ++ if (mctrl & tiocmbit) \ ++ cr |= uartbit; \ ++ else \ ++ cr &= ~uartbit; \ ++ } while (0) ++ ++ TIOCMBIT(TIOCM_RTS, REG_CR_RTS); ++ TIOCMBIT(TIOCM_DTR, REG_CR_DTR); ++ TIOCMBIT(TIOCM_OUT1, REG_CR_OUT1); ++ TIOCMBIT(TIOCM_OUT2, REG_CR_OUT2); ++ TIOCMBIT(TIOCM_LOOP, REG_CR_LBE); ++ ++ if (port->status & UPSTAT_AUTORTS) { ++ /* We need to disable auto-RTS if we want to turn RTS off */ ++ TIOCMBIT(TIOCM_RTS, REG_CR_RTSEN); ++ } ++#undef TIOCMBIT ++ ++ phytium_uart_write(cr, pup, REG_CR); ++} ++ ++static unsigned int phytium_get_mctrl(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int cr = 0; ++ unsigned int status = phytium_uart_read(pup, REG_FR); ++ ++#define TIOCMBIT(uartbit, tiocmbit) \ ++ do { \ ++ if (status & uartbit) \ ++ cr |= tiocmbit; \ ++ } while (0) ++ ++ TIOCMBIT(REG_FR_DCD, TIOCM_CAR); ++ TIOCMBIT(REG_FR_DSR, TIOCM_DSR); ++ TIOCMBIT(REG_FR_CTS, TIOCM_CTS); ++ TIOCMBIT(REG_FR_RI, TIOCM_RNG); ++#undef TIOCMBIT ++ return cr; ++} ++ ++static void phytium_start_tx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ if (phytium_tx_chars(pup, false)) { ++ pup->im |= REG_IMSC_TXIM; ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++ } ++} ++ ++static void phytium_stop_rx(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ pup->im &= ~(REG_IMSC_RXIM|REG_IMSC_RTIM|REG_IMSC_FEIM| ++ REG_IMSC_PEIM|REG_IMSC_BEIM|REG_IMSC_OEIM); ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++} ++ ++static void phytium_enable_ms(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ pup->im |= REG_IMSC_RIMIM|REG_IMSC_CTSMIM|REG_IMSC_DCDMIM|REG_IMSC_DSRMIM; ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++} ++ ++static void phytium_break_ctl(struct uart_port *port, int break_state) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned long flags; ++ unsigned int lcr_h; ++ ++ spin_lock_irqsave(&pup->port.lock, flags); ++ lcr_h = phytium_uart_read(pup, REG_LCRH_TX); ++ if (break_state == -1) ++ lcr_h |= REG_LCRH_BRK; ++ else ++ lcr_h &= ~REG_LCRH_BRK; ++ phytium_uart_write(lcr_h, pup, REG_LCRH_TX); ++ spin_unlock_irqrestore(&pup->port.lock, flags); ++} ++ ++static int phytium_hwinit(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ /* XXX: more configurable setup method in future */ ++ pup->port.uartclk = DEFAULT_UARTCLK; ++ ++ /* Clear pending error and receive interrupts */ ++ phytium_uart_write(REG_ICR_OEIS | REG_ICR_BEIS | REG_ICR_PEIS | ++ REG_ICR_FEIS | REG_ICR_RTIS | REG_ICR_RXIS, ++ pup, REG_ICR); ++ ++ /* ++ * Save interrupts enable mask, and enable RX interrupts in case if ++ * the interrupt is used for NMI entry. ++ */ ++ pup->im = phytium_uart_read(pup, REG_IMSC); ++ phytium_uart_write(REG_IMSC_RTIM | REG_IMSC_RXIM, pup, REG_IMSC); ++ ++ return 0; ++} ++ ++static int phytium_uart_allocate_irq(struct phytium_uart_port *pup) ++{ ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++ ++ return request_irq(pup->port.irq, phytium_uart_interrupt, IRQF_SHARED, DRV_NAME, pup); ++} ++ ++static void phytium_enable_interrtups(struct phytium_uart_port *pup) ++{ ++ unsigned int i; ++ ++ spin_lock_irq(&pup->port.lock); ++ ++ /* Clear out any spuriously appearing RX interrupts */ ++ phytium_uart_write(REG_ICR_RTIS | REG_ICR_RXIS, pup, REG_ICR); ++ ++ /* ++ * RXIS is asserted only when the RX FIFO transitions from below ++ * to above the trigger threshold. If the RX FIFO is already ++ * full to the threashold this can't happen and RXIS will now be ++ * stuck off. Drain the RX FIFO explicitly to fix this: ++ */ ++ for (i = 0; i < pup->port.fifosize * 2; i++) { ++ if (phytium_uart_read(pup, REG_FR) & REG_FR_RXFE) ++ break; ++ ++ phytium_uart_read(pup, REG_DR); ++ } ++ ++ pup->im = REG_IMSC_RTIM | REG_IMSC_RXIM; ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++ spin_unlock_irq(&pup->port.lock); ++} ++ ++static int phytium_startup(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int cr; ++ int ret = 0; ++ ++ ret = phytium_hwinit(port); ++ if (ret) ++ goto out; ++ ++ ret = phytium_uart_allocate_irq(pup); ++ if (ret) ++ goto out; ++ ++ phytium_uart_write(REG_IFLS_RX4_8|REG_IFLS_TX4_8, pup, REG_IFLS); ++ ++ spin_lock_irq(&pup->port.lock); ++ ++ /* restore RTS and DTR */ ++ cr = pup->old_cr & (REG_CR_RTS | REG_CR_DTR); ++ cr |= REG_CR_UARTEN | REG_CR_RXE | REG_CR_TXE; ++ phytium_uart_write(cr, pup, REG_CR); ++ ++ spin_unlock_irq(&pup->port.lock); ++ ++ /* initialise the old status of the modem signals */ ++ pup->old_status = phytium_uart_read(pup, REG_FR) & (REG_FR_DCD|REG_FR_DSR|REG_FR_CTS); ++ ++ phytium_enable_interrtups(pup); ++ ++out: ++ return ret; ++} ++ ++static void phytium_shutdown_channel(struct phytium_uart_port *pup, ++ unsigned int lcrh) ++{ ++ unsigned long val; ++ ++ val = phytium_uart_read(pup, lcrh); ++ val &= ~(REG_LCRH_BRK | REG_LCRH_FEN); ++ phytium_uart_write(val, pup, lcrh); ++} ++ ++static void phytium_disable_uart(struct phytium_uart_port *pup) ++{ ++ unsigned int cr; ++ ++ pup->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); ++ spin_lock_irq(&pup->port.lock); ++ cr = phytium_uart_read(pup, REG_CR); ++ pup->old_cr = cr; ++ cr &= REG_CR_RTS | REG_CR_DTR; ++ cr |= REG_CR_UARTEN | REG_CR_TXE; ++ phytium_uart_write(cr, pup, REG_CR); ++ spin_unlock_irq(&pup->port.lock); ++ ++ /* ++ * disable break condition and fifos ++ */ ++ phytium_shutdown_channel(pup, REG_LCRH_RX); ++} ++ ++static void phytium_disable_interrupts(struct phytium_uart_port *pup) ++{ ++ spin_lock_irq(&pup->port.lock); ++ ++ /* mask all interrupts and clear all pending ones */ ++ pup->im = 0; ++ phytium_uart_write(pup->im, pup, REG_IMSC); ++ phytium_uart_write(0xffff, pup, REG_ICR); ++ ++ spin_unlock_irq(&pup->port.lock); ++} ++ ++static void phytium_shutdown(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ ++ phytium_disable_interrupts(pup); ++ ++ free_irq(pup->port.irq, pup); ++ ++ phytium_disable_uart(pup); ++ ++ if (pup->port.ops->flush_buffer) ++ pup->port.ops->flush_buffer(port); ++} ++ ++static void ++phytium_setup_status_masks(struct uart_port *port, struct ktermios *termios) ++{ ++ port->read_status_mask = REG_DR_OE | 255; ++ if (termios->c_iflag & INPCK) ++ port->read_status_mask |= REG_DR_FE | REG_DR_PE; ++ if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) ++ port->read_status_mask |= REG_DR_BE; ++ ++ /* ++ * Characters to ignore ++ */ ++ port->ignore_status_mask = 0; ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= REG_DR_FE | REG_DR_PE; ++ if (termios->c_iflag & IGNBRK) { ++ port->ignore_status_mask |= REG_DR_BE; ++ /* ++ * If we're ignoring parity and break indicators, ++ * ignore overruns too (for real raw support). ++ */ ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= REG_DR_OE; ++ } ++ ++ /* ++ * Ignore all characters if CREAD is not set. ++ */ ++ if ((termios->c_cflag & CREAD) == 0) ++ port->ignore_status_mask |= UART_DUMMY_DR_RX; ++} ++ ++static void ++phytium_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ unsigned int lcr_h, old_cr; ++ unsigned long flags; ++ unsigned int baud, quot; ++ ++ /* Ask the core to calculate the divisor for us. */ ++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); ++ ++ if (baud > port->uartclk/16) ++ quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); ++ else ++ quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud); ++ ++ switch (termios->c_cflag & CSIZE) { ++ case CS5: ++ lcr_h = REG_LCRH_WLEN_5; ++ break; ++ case CS6: ++ lcr_h = REG_LCRH_WLEN_6; ++ break; ++ case CS7: ++ lcr_h = REG_LCRH_WLEN_7; ++ break; ++ default: /* CS8 */ ++ lcr_h = REG_LCRH_WLEN_8; ++ break; ++ } ++ if (termios->c_cflag & CSTOPB) ++ lcr_h |= REG_LCRH_STP2; ++ if (termios->c_cflag & PARENB) { ++ lcr_h |= REG_LCRH_PEN; ++ if (!(termios->c_cflag & PARODD)) ++ lcr_h |= REG_LCRH_EPS; ++ if (termios->c_cflag & CMSPAR) ++ lcr_h |= REG_LCRH_SPS; ++ } ++ if (pup->port.fifosize > 1) ++ lcr_h |= REG_LCRH_FEN; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ ++ /* ++ * Update the per-port timeout. ++ */ ++ uart_update_timeout(port, termios->c_cflag, baud); ++ ++ phytium_setup_status_masks(port, termios); ++ ++ if (UART_ENABLE_MS(port, termios->c_cflag)) ++ phytium_enable_ms(port); ++ ++ /* first, disable everything */ ++ old_cr = phytium_uart_read(pup, REG_CR); ++ phytium_uart_write(0, pup, REG_CR); ++ ++ if (termios->c_cflag & CRTSCTS) { ++ if (old_cr & REG_CR_RTS) ++ old_cr |= REG_CR_RTSEN; ++ ++ old_cr |= REG_CR_CTSEN; ++ port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; ++ } else { ++ old_cr &= ~(REG_CR_CTSEN | REG_CR_RTSEN); ++ port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); ++ } ++ ++ /* Set baud rate */ ++ phytium_uart_write(quot & 0x3f, pup, REG_FBRD); ++ phytium_uart_write(quot >> 6, pup, REG_IBRD); ++ ++ phytium_uart_write(lcr_h, pup, REG_LCRH_RX); ++ phytium_uart_write(old_cr, pup, REG_CR); ++ ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++static const char *phytium_type(struct uart_port *port) ++{ ++ struct phytium_uart_port *pup = ++ container_of(port, struct phytium_uart_port, port); ++ return pup->port.type == PORT_PHYTIUM ? pup->type : NULL; ++} ++ ++static void phytium_release_port(struct uart_port *port) ++{ ++ /* Nothing to release ... */ ++} ++ ++static int phytium_request_port(struct uart_port *port) ++{ ++ /* UARTs always present */ ++ return 0; ++} ++ ++static void phytium_config_port(struct uart_port *port, int flags) ++{ ++ if (flags & UART_CONFIG_TYPE) { ++ port->type = PORT_PHYTIUM; ++ phytium_request_port(port); ++ } ++} ++ ++static int phytium_verify_port(struct uart_port *port, struct serial_struct *ser) ++{ ++ int ret = 0; ++ ++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_PHYTIUM) ++ ret = -EINVAL; ++ if (ser->irq < 0 || ser->irq >= nr_irqs) ++ ret = -EINVAL; ++ if (ser->baud_base < 9600) ++ ret = -EINVAL; ++ ++ return ret; ++} ++ ++static const struct uart_ops phytium_uart_ops = { ++ .tx_empty = phytium_tx_empty, ++ .set_mctrl = phytium_set_mctrl, ++ .get_mctrl = phytium_get_mctrl, ++ .stop_tx = phytium_stop_tx, ++ .start_tx = phytium_start_tx, ++ .stop_rx = phytium_stop_rx, ++ .enable_ms = phytium_enable_ms, ++ .break_ctl = phytium_break_ctl, ++ .startup = phytium_startup, ++ .shutdown = phytium_shutdown, ++ .set_termios = phytium_set_termios, ++ .type = phytium_type, ++ .release_port = phytium_release_port, ++ .request_port = phytium_request_port, ++ .config_port = phytium_config_port, ++ .verify_port = phytium_verify_port, ++}; ++ ++static struct phytium_uart_port *uart_ports[UART_NR]; ++ ++static struct uart_driver phytium_uart = { ++ .owner = THIS_MODULE, ++ .driver_name = DRV_NAME, ++ .dev_name = "ttyFTX", ++ .nr = UART_NR, ++}; ++ ++void phytium_unregister_port(struct phytium_uart_port *pup) ++{ ++ int i; ++ bool busy = false; ++ ++ for (i = 0; i < ARRAY_SIZE(uart_ports); i++) { ++ if (uart_ports[i] == pup) ++ uart_ports[i] = NULL; ++ else if (uart_ports[i]) ++ busy = true; ++ } ++ ++ if (!busy) ++ uart_unregister_driver(&phytium_uart); ++} ++ ++static int phytium_find_free_port(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(uart_ports); i++) ++ if (uart_ports[i] == NULL) ++ return i; ++ ++ return -EBUSY; ++} ++ ++static int phytium_register_port(struct phytium_uart_port *pup) ++{ ++ int rc; ++ ++ /* Ensure interrupts from this UART are masked and cleared */ ++ phytium_uart_write(0, pup, REG_IMSC); ++ phytium_uart_write(0xffff, pup, REG_ICR); ++ ++ if (!phytium_uart.state) { ++ rc = uart_register_driver(&phytium_uart); ++ if (rc < 0) { ++ dev_err(pup->port.dev, ++ "Failed to register Phytium PCI UART driver\n"); ++ return rc; ++ } ++ } ++ ++ rc = uart_add_one_port(&phytium_uart, &pup->port); ++ if (rc) ++ phytium_unregister_port(pup); ++ ++ return rc; ++} ++ ++static int phytium_uart_probe(struct pci_dev *pdev, ++ const struct pci_device_id *id) ++{ ++ struct phytium_uart_port *pup; ++ int portnr, rc; ++ ++ portnr = phytium_find_free_port(); ++ if (portnr < 0) ++ return portnr; ++ ++ pup = devm_kzalloc(&pdev->dev, sizeof(struct phytium_uart_port), ++ GFP_KERNEL); ++ if (!pup) ++ return -ENOMEM; ++ ++ rc = pcim_enable_device(pdev); ++ if (rc) ++ return rc; ++ ++ rc = pcim_iomap_regions_request_all(pdev, 0x01, pci_name(pdev)); ++ if (rc) ++ return rc; ++ ++ pup->port.iotype = UPIO_MEM32; ++ pup->port.irq = pdev->irq; ++ pup->port.mapbase = pci_resource_start(pdev, 0); ++ pup->port.membase = pcim_iomap_table(pdev)[0]; ++ pup->port.ops = &phytium_uart_ops; ++ pup->port.dev = &pdev->dev; ++ pup->port.fifosize = 32; ++ pup->port.flags = UPF_BOOT_AUTOCONF; ++ pup->port.line = portnr; ++ ++ uart_ports[portnr] = pup; ++ ++ pup->old_cr = 0; ++ snprintf(pup->type, sizeof(pup->type), "pci-uart"); ++ ++ pci_set_drvdata(pdev, pup); ++ ++ return phytium_register_port(pup); ++} ++ ++static void phytium_uart_remove(struct pci_dev *pdev) ++{ ++ struct phytium_uart_port *pup = pci_get_drvdata(pdev); ++ ++ uart_remove_one_port(&phytium_uart, &pup->port); ++ phytium_unregister_port(pup); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int phytium_uart_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct phytium_uart_port *pup = pci_get_drvdata(pdev); ++ ++ if (pup) ++ uart_suspend_port(&phytium_uart, &pup->port); ++ ++ return 0; ++} ++ ++static int phytium_uart_resume(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct phytium_uart_port *pup = pci_get_drvdata(pdev); ++ ++ if (pup) ++ uart_resume_port(&phytium_uart, &pup->port); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(phytium_dev_pm_ops, phytium_uart_suspend, phytium_uart_resume); ++ ++static const struct pci_device_id pci_ids[] = { ++ { PCI_VDEVICE(PHYTIUM, 0xdc2e) }, ++ { 0 } ++}; ++MODULE_DEVICE_TABLE(pci, pci_ids); ++ ++static struct pci_driver phytium_uart_pci_driver = { ++ .name = DRV_NAME, ++ .probe = phytium_uart_probe, ++ .remove = phytium_uart_remove, ++ .driver = { ++ .pm = &phytium_dev_pm_ops, ++ }, ++ .id_table = pci_ids, ++}; ++ ++static int __init phytium_uart_init(void) ++{ ++ pr_info("Serial: Phytium PCI UART driver\n"); ++ ++ return pci_register_driver(&phytium_uart_pci_driver); ++} ++ ++static void __exit phytium_uart_exit(void) ++{ ++ pci_unregister_driver(&phytium_uart_pci_driver); ++} ++ ++module_init(phytium_uart_init); ++module_exit(phytium_uart_exit); ++ ++MODULE_AUTHOR("Chen Baozi "); ++MODULE_DESCRIPTION("Phytium PCI serial port driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index a8a9addb4d25..d2e0f64a4424 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2472,8 +2472,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + * and our use of dma addresses in the trb_address_map radix tree needs + * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need. + */ +- xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, +- TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); ++ if (xhci->quirks & XHCI_TRB_OVERFETCH) ++ /* Buggy HC prefetches beyond segment bounds - allocate dummy space at the end */ ++ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, ++ TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2); ++ else ++ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, ++ TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); + + /* See Table 46 and Note on Figure 55 */ + xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index aff65cefead2..4ab988c0321f 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -36,6 +36,8 @@ + #define PCI_VENDOR_ID_ETRON 0x1b6f + #define PCI_DEVICE_ID_EJ168 0x7023 + ++#define PCI_DEVICE_ID_VIA_VL805 0x3483 ++ + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 + #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1 +@@ -288,8 +290,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + pdev->device == 0x3432) + xhci->quirks |= XHCI_BROKEN_STREAMS; + +- if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) { ++ if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) { + xhci->quirks |= XHCI_LPM_SUPPORT; ++ xhci->quirks |= XHCI_TRB_OVERFETCH; + xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS; + } + +@@ -330,6 +333,18 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) + xhci->quirks |= XHCI_NO_SOFT_RETRY; + ++ if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { ++ xhci->quirks |= XHCI_ZHAOXIN_HOST; ++ ++ if (pdev->device == 0x9202) { ++ xhci->quirks |= XHCI_RESET_ON_RESUME; ++ xhci->quirks |= XHCI_TRB_OVERFETCH; ++ } ++ ++ if (pdev->device == 0x9203) ++ xhci->quirks |= XHCI_TRB_OVERFETCH; ++ } ++ + /* xHC spec requires PCI devices to support D3hot and D3cold */ + if (xhci->hci_version >= 0x120) + xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index eb0d5a8c2b78..ef1e3df7e4d1 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -115,6 +115,10 @@ static int xhci_plat_start(struct usb_hcd *hcd) + return xhci_run(hcd); + } + ++static const struct xhci_plat_priv xhci_plat_phytium_pe220x = { ++ .quirks = XHCI_RESET_ON_RESUME | XHCI_S1_SUSPEND_WAKEUP, ++}; ++ + #ifdef CONFIG_OF + static const struct xhci_plat_priv xhci_plat_marvell_armada = { + .init_quirk = xhci_mvebu_mbus_init_quirk, +@@ -137,10 +141,6 @@ static const struct xhci_plat_priv xhci_plat_brcm = { + .quirks = XHCI_RESET_ON_RESUME | XHCI_SUSPEND_RESUME_CLKS, + }; + +-static const struct xhci_plat_priv xhci_plat_phytium_pe220x = { +- .quirks = XHCI_RESET_ON_RESUME, +-}; +- + static const struct of_device_id usb_xhci_of_match[] = { + { + .compatible = "generic-xhci", +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index b69b8c7e7966..0bc5f46c72a6 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2930,6 +2930,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + goto out; + } + ++ if ((status & STS_WAKEUP) && (xhci->quirks & XHCI_S1_SUSPEND_WAKEUP)) { ++ status |= STS_WAKEUP; ++ writel(status, &xhci->op_regs->status); ++ ret = IRQ_HANDLED; ++ } ++ + if (!(status & STS_EINT)) + goto out; + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 473b0b64dd57..bc13c0f01b31 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1074,6 +1074,17 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) + return -ETIMEDOUT; + } + } ++ ++ if (xhci->quirks & XHCI_S1_SUSPEND_WAKEUP) { ++ if (device_may_wakeup(xhci_to_hcd(xhci)->self.controller) && do_wakeup) { ++ if (enable_irq_wake(hcd->irq)) ++ xhci_err(xhci, "failed to enable irq wakes\n"); ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ if (xhci->shared_hcd) ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); ++ } ++ } ++ + spin_unlock_irq(&xhci->lock); + + /* +@@ -1123,6 +1134,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + time_before(jiffies, xhci->usb3_rhub.bus_state.next_statechange)) + msleep(100); + ++ if (xhci->quirks & XHCI_S1_SUSPEND_WAKEUP) { ++ if (device_may_wakeup(xhci_to_hcd(xhci)->self.controller)) { ++ if (disable_irq_wake(hcd->irq)) ++ xhci_err(xhci, "failed to disable irq wakes\n"); ++ } ++ } ++ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index c7749f6e3474..713722b4f83b 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -239,6 +239,8 @@ struct xhci_op_regs { + /* USBSTS - USB status - status bitmasks */ + /* HC not running - set to 1 when run/stop bit is cleared. */ + #define STS_HALT XHCI_STS_HALT ++/* event wakeup interrupt */ ++#define STS_WAKEUP (1 << 1) + /* serious error, e.g. PCI parity error. The HC will clear the run/stop bit. */ + #define STS_FATAL (1 << 2) + /* event interrupt - clear this prior to clearing any IP flags in IR set*/ +@@ -1895,6 +1897,9 @@ struct xhci_hcd { + #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) + #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) + #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) ++#define XHCI_TRB_OVERFETCH BIT_ULL(45) ++#define XHCI_ZHAOXIN_HOST BIT_ULL(46) ++#define XHCI_S1_SUSPEND_WAKEUP BIT_ULL(47) + + unsigned int num_active_eps; + unsigned int limit_active_eps; +diff --git a/drivers/usb/phytium/Kconfig b/drivers/usb/phytium/Kconfig +index f131a3f8865a..2cb04f672c07 100644 +--- a/drivers/usb/phytium/Kconfig ++++ b/drivers/usb/phytium/Kconfig +@@ -6,3 +6,14 @@ config USB_PHYTIUM + + If you choose to build this driver is a dynamically linked modules, the module will + be called phytium-usb.ko ++ ++config USB_PHYTIUM_PCI ++ tristate "PHYTIUM PCI USB Support" ++ default n ++ depends on USB ++ depends on USB_GADGET ++ help ++ Say Y or M here if your system has a OTG USB Controller based on PHYTIUM SOC. ++ ++ If you choose to build this driver is a dynamically linked modules, the module will ++ be called phytium-usb-pci.ko +diff --git a/drivers/usb/phytium/Makefile b/drivers/usb/phytium/Makefile +index 05d422d4a59b..e176c334cba5 100644 +--- a/drivers/usb/phytium/Makefile ++++ b/drivers/usb/phytium/Makefile +@@ -1,5 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-$(CONFIG_USB_PHYTIUM) += phytium-usb.o ++obj-$(CONFIG_USB_PHYTIUM_PCI) += phytium-usb-pci.o + + phytium-usb-y := core.o dma.o platform.o host.o gadget.o ++phytium-usb-pci-y := core.o dma.o pci.o host.o gadget.o +diff --git a/drivers/usb/phytium/core.c b/drivers/usb/phytium/core.c +index c0182c0770e5..ed2d1d661c2d 100644 +--- a/drivers/usb/phytium/core.c ++++ b/drivers/usb/phytium/core.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include "core.h" + + int phytium_core_reset(struct phytium_cusb *config, bool skip_wait) +diff --git a/drivers/usb/phytium/core.h b/drivers/usb/phytium/core.h +index f563672ccaa9..0237476bea66 100644 +--- a/drivers/usb/phytium/core.h ++++ b/drivers/usb/phytium/core.h +@@ -1,5 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #ifndef __PHYTIUM_CORE_H__ + #define __PHYTIUM_CORE_H__ + +diff --git a/drivers/usb/phytium/dma.c b/drivers/usb/phytium/dma.c +index 2e0d6df3eb34..b61b02c1dc2c 100644 +--- a/drivers/usb/phytium/dma.c ++++ b/drivers/usb/phytium/dma.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include + #include + #include "core.h" +@@ -416,7 +420,7 @@ static int32_t phytium_dma_channelRelease(struct DMA_CONTROLLER *priv, struct DM + } + } + +- channel->status = DMA_STATUS_UNKNOW; ++ channel->status = DMA_STATUS_UNKNOWN; + + return 0; + } +@@ -646,7 +650,7 @@ static enum DMA_Status phytium_dma_getChannelStatus(struct DMA_CONTROLLER *priv, + uint32_t ep_cmd, ep_sts; + + if (!priv || !channel) +- return DMA_STATUS_UNKNOW; ++ return DMA_STATUS_UNKNOWN; + + if (channel->status >= DMA_STATUS_BUSY) { + phytium_write32(&priv->regs->ep_sel, channel->isDirTx | channel->hwUsbEppNum); +@@ -692,7 +696,7 @@ static int32_t phytium_dma_channelAbort(struct DMA_CONTROLLER *priv, struct DMA_ + } + } + } +- if (channel->status != DMA_STATUS_UNKNOW) ++ if (channel->status != DMA_STATUS_UNKNOWN) + channel->status = DMA_STATUS_FREE; + + return 0; +diff --git a/drivers/usb/phytium/dma.h b/drivers/usb/phytium/dma.h +index 073a078c1289..3d58e06bc146 100644 +--- a/drivers/usb/phytium/dma.h ++++ b/drivers/usb/phytium/dma.h +@@ -1,5 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #ifndef __PHYTIUM_DMA_H__ + #define __PHYTIUM_DMA_H__ + +@@ -61,7 +65,7 @@ struct DMA_Trb { + }; + + enum DMA_Status { +- DMA_STATUS_UNKNOW, ++ DMA_STATUS_UNKNOWN, + DMA_STATUS_FREE, + DMA_STATUS_ABORT, + DMA_STATUS_BUSY, +diff --git a/drivers/usb/phytium/gadget.c b/drivers/usb/phytium/gadget.c +index afcb846c8db3..0c07819b9744 100644 +--- a/drivers/usb/phytium/gadget.c ++++ b/drivers/usb/phytium/gadget.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include + #include "gadget.h" + #include "dma.h" +diff --git a/drivers/usb/phytium/gadget.h b/drivers/usb/phytium/gadget.h +index d87b55ade7a7..6d7bd4b32859 100644 +--- a/drivers/usb/phytium/gadget.h ++++ b/drivers/usb/phytium/gadget.h +@@ -1,5 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #ifndef __PHYTIUM_GADGET_H_ + #define __PHYTIUM_GADGET_H_ + +diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c +index f0da060cf04e..888770dcf3c8 100644 +--- a/drivers/usb/phytium/host.c ++++ b/drivers/usb/phytium/host.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include + #include + #include +@@ -11,7 +15,7 @@ + + #define DRV_NAME "phytium_usb" + +-#define HOST_GENERIC_EP_CONTROLL 0x00 ++#define HOST_GENERIC_EP_CONTROL 0x00 + #define HOST_GENERIC_EP_ISOC 0x01 + #define HOST_GENERIC_EP_BULK 0x02 + #define HOST_GENERIC_EP_INT 0x03 +@@ -795,7 +799,7 @@ static void hostStartReq(struct HOST_CTRL *priv, struct HOST_REQ *req) + case USB_ENDPOINT_XFER_CONTROL: + usbReq = getNextReq(hostEp); + +- priv->in[HOST_GENERIC_EP_CONTROLL].scheduledUsbHEp = hostEp; ++ priv->in[HOST_GENERIC_EP_CONTROL].scheduledUsbHEp = hostEp; + priv->ep0State = HOST_EP0_STAGE_SETUP; + hostEpPriv->currentHwEp = hostEpPriv->genericHwEp; + hostEpPriv->genericHwEp->scheduledUsbHEp = hostEp; +@@ -980,7 +984,7 @@ static int32_t hostEp0Irq(struct HOST_CTRL *priv, uint8_t isIn) + if (!priv) + return ret; + +- hwEp = isIn ? &priv->in[HOST_GENERIC_EP_CONTROLL] : &priv->out[HOST_GENERIC_EP_CONTROLL]; ++ hwEp = isIn ? &priv->in[HOST_GENERIC_EP_CONTROL] : &priv->out[HOST_GENERIC_EP_CONTROL]; + hostEp = hwEp->scheduledUsbHEp; + usbHEpPriv = (struct HOST_EP_PRIV *)hostEp->hcPriv; + +@@ -1016,13 +1020,13 @@ static int32_t hostEp0Irq(struct HOST_CTRL *priv, uint8_t isIn) + switch (priv->ep0State) { + case HOST_EP0_STAGE_IN: + pr_debug("Ep0 Data IN\n"); +- usbHEpPriv->currentHwEp = &priv->out[HOST_GENERIC_EP_CONTROLL]; ++ usbHEpPriv->currentHwEp = &priv->out[HOST_GENERIC_EP_CONTROL]; + usbReq->actualLength = length; + priv->ep0State = HOST_EP0_STAGE_STATUSOUT; + break; + case HOST_EP0_STAGE_OUT: + pr_debug("Ep0 Data OUT\n"); +- usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROLL]; ++ usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROL]; + usbReq->actualLength = length; + priv->ep0State = HOST_EP0_STAGE_STATUSIN; + break; +@@ -1031,12 +1035,12 @@ static int32_t hostEp0Irq(struct HOST_CTRL *priv, uint8_t isIn) + if (!usbReq->setup->wLength) { + pr_debug("EP0_STAGE_STATUSIN\n"); + priv->ep0State = HOST_EP0_STAGE_STATUSIN; +- usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROLL]; ++ usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROL]; + break; + } else if (usbReq->setup->bRequestType & USB_DIR_IN) { + pr_debug("EP0_STAGE_STAGE_IN\n"); + priv->ep0State = HOST_EP0_STAGE_IN; +- usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROLL]; ++ usbHEpPriv->currentHwEp = &priv->in[HOST_GENERIC_EP_CONTROL]; + nextStage = 1; + break; + } +@@ -1066,7 +1070,7 @@ static int32_t hostEp0Irq(struct HOST_CTRL *priv, uint8_t isIn) + scheduleNextTransfer(priv, usbReq, hwEp); + } + +- return 0; ++ return ret; + } + + static void updateTimeIntTransfer(struct list_head *head, struct HOST_EP_PRIV *lastFinished) +@@ -2079,6 +2083,7 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, int spee + speed == USB_SPEED_FULL ? "" : "micro"); + break; + } ++ fallthrough; + /* fall through */ + case USB_SPEED_LOW: + if (usb_endpoint_xfer_int(&desc) || usb_endpoint_xfer_isoc(&desc)) { +diff --git a/drivers/usb/phytium/host_api.h b/drivers/usb/phytium/host_api.h +index b99d2b4980fb..6003954eb1b1 100644 +--- a/drivers/usb/phytium/host_api.h ++++ b/drivers/usb/phytium/host_api.h +@@ -1,5 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #ifndef __PHYTIUM_HOST_API_H_ + #define __PHYTIUM_HOST_API_H_ + +diff --git a/drivers/usb/phytium/hw-regs.h b/drivers/usb/phytium/hw-regs.h +index 8da9f8e9b925..8200ac3cf7b7 100644 +--- a/drivers/usb/phytium/hw-regs.h ++++ b/drivers/usb/phytium/hw-regs.h +@@ -1,4 +1,9 @@ + /* SPDX-License-Identifier: GPL-2.0 */ ++ ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #ifndef __LINUX_PHYTIUM_HW_REGS + #define __LINUX_PHYTIUM_HW_REGS + +diff --git a/drivers/usb/phytium/pci.c b/drivers/usb/phytium/pci.c +index 964fd67bfc53..72adf1aa39e9 100644 +--- a/drivers/usb/phytium/pci.c ++++ b/drivers/usb/phytium/pci.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include + #include + #include +diff --git a/drivers/usb/phytium/platform.c b/drivers/usb/phytium/platform.c +index bcf5859a4d18..5d3ec8793d07 100644 +--- a/drivers/usb/phytium/platform.c ++++ b/drivers/usb/phytium/platform.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-3.0 + ++/* ++ * Copyright (c) 2022, Phytium Technology Co., Ltd. ++ */ ++ + #include + #include + //#include +diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h +index 851b982f8c4b..f08747fd29a0 100644 +--- a/include/uapi/linux/serial_core.h ++++ b/include/uapi/linux/serial_core.h +@@ -279,4 +279,11 @@ + /* Freescale LINFlexD UART */ + #define PORT_LINFLEXUART 122 + ++ ++/* Phytium PCI UART ++ * use bigger value to aviod code confilct ++ * when update in the future. ++ */ ++#define PORT_PHYTIUM 200 ++ + #endif /* _UAPILINUX_SERIAL_CORE_H */ diff --git a/target/linux/phytium/uefi/config-5.10 b/target/linux/phytium/uefi/config-5.10 index 5fe4d5e5a1ce96cb8772a289c3b70dbd5e9c10dd..85337852152d1d8acb95c44307c8b68aaf87eb03 100644 --- a/target/linux/phytium/uefi/config-5.10 +++ b/target/linux/phytium/uefi/config-5.10 @@ -4,7 +4,8 @@ CONFIG_ACPI_BATTERY=y # CONFIG_ACPI_BGRT is not set CONFIG_ACPI_CCA_REQUIRED=y CONFIG_ACPI_CONTAINER=y -# CONFIG_ACPI_CPPC_CPUFREQ is not set +CONFIG_ACPI_CPPC_CPUFREQ=y +CONFIG_ACPI_CPPC_LIB=y # CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUGGER is not set # CONFIG_ACPI_DOCK is not set @@ -88,7 +89,7 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_CLUT224=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_PCC is not set +CONFIG_PCC=y CONFIG_PCI_LABEL=y # CONFIG_PMIC_OPREGION is not set CONFIG_PNP=y