2020-04-17 07:49:03

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

From: Yan-Hsuan Chuang <[email protected]>

Although RTL8723DE devices are 802.11n devices, while rtw88
aimed to support for 802.11ac devices, the 8723DE devices's
architecture is relatively close to the 802.11ac devices.
So, add support for them on rtw88, with some minor modifications.

Basically their TRX paths are the same, except that 8723DE
does not have H2CQ for H2C commands and the corresponding
HIMR3/HISR3 for H2CQ. Another thing is that 8723DE uses a
different way to download firmware, so it cannot share with
8822BE/8822CE mac firmware download routine.

For easier to review, the 8723DE implementation is split into
multiple patches. One can review on it to see the difference
of the chip's functionalities.

With 8723DE joining rtw88, we found that the core kernel
module's size increases a lot. It's because the various tables
for each chip are built into the core module. Note that the
tables usually come up to 10+ K lines. Imagine that a user
only uses 8822CE, but the tables of 8822BE will also be loaded
into the kernel, waste a lot of the memory.

Hence, extract the various tables for each chip into separate
modules corresponding to 8822B/8822C/8723D. That way, once one
of the device, for example 8822CE, is probed, only 8822C's
tables in rtw88_8822c.ko will be loaded and its pci part, it
can reduce the usage of kernel memory.

Finally, to make them look consistent and avoid confusion,
rename the core module and the pci module with prefix "rtw88_".


Ping-Ke Shih (33):
rtw88: 8723d: Add basic chip capabilities
rtw88: 8723d: add beamform wrapper functions
rtw88: 8723d: Add power sequence
rtw88: 8723d: Add RF read/write ops
rtw88: 8723d: Add mac/bb/rf/agc/power_limit tables
rtw88: 8723d: Add cfg_ldo25 to control LDO25
rtw88: 8723d: Add new chip op efuse_grant() to control efuse access
rtw88: 8723d: Add read_efuse to recognize efuse info from map
rtw88: add legacy firmware download for 8723D devices
rtw88: no need to send additional information to legacy firmware
rtw88: 8723d: Add mac power-on/-off function
rtw88: decompose while(1) loop of power sequence polling command
rtw88: 8723d: 11N chips don't support H2C queue
rtw88: 8723d: implement set_tx_power_index ops
rtw88: 8723d: Organize chip TX/RX FIFO
rtw88: 8723d: initialize mac/bb/rf basic functions
rtw88: 8723d: Add DIG parameter
rtw88: 8723d: Add query_rx_desc
rtw88: 8723d: Add set_channel
rtw88: handle C2H_CCX_TX_RPT to know if packet TX'ed successfully
rtw88: 8723d: 11N chips don't support LDPC
rtw88: 8723d: Add chip_ops::false_alarm_statistics
rtw88: 8723d: Set IG register for CCK rate
rtw88: 8723d: add interface configurations table
rtw88: 8723d: Add LC calibration
rtw88: 8723d: add IQ calibration
rtw88: 8723d: Add power tracking
rtw88: 8723d: Add shutdown callback to disable BT USB suspend
rtw88: 8723d: implement flush queue
rtw88: 8723d: set ltecoex register address in chip_info
rtw88: 8723d: Add coex support
rtw88: fill zeros to words 0x06 and 0x07 of security cam entry
rtw88: 8723d: Add 8723DE to Kconfig and Makefile

Yan-Hsuan Chuang (1):
rtw88: rename rtw88.ko/rtwpci.ko to rtw88_core.ko/rtw88_pci.ko

Zong-Zhe Yang (6):
rtw88: extract: export symbols used in chip functionalities
rtw88: extract: export symbols about pci interface
rtw88: extract: make 8822c an individual kernel module
rtw88: extract: make 8822b an individual kernel module
rtw88: extract: make 8723d an individual kernel module
rtw88: extract: remove the unused after extracting

drivers/net/wireless/realtek/rtw88/Kconfig | 26 +-
drivers/net/wireless/realtek/rtw88/Makefile | 28 +-
drivers/net/wireless/realtek/rtw88/bf.c | 14 +-
drivers/net/wireless/realtek/rtw88/bf.h | 22 +
drivers/net/wireless/realtek/rtw88/coex.c | 3 +
drivers/net/wireless/realtek/rtw88/debug.c | 9 +-
drivers/net/wireless/realtek/rtw88/efuse.c | 4 +
drivers/net/wireless/realtek/rtw88/fw.c | 34 +-
drivers/net/wireless/realtek/rtw88/fw.h | 32 +-
drivers/net/wireless/realtek/rtw88/mac.c | 435 ++-
drivers/net/wireless/realtek/rtw88/mac.h | 1 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 7 +-
drivers/net/wireless/realtek/rtw88/main.c | 55 +-
drivers/net/wireless/realtek/rtw88/main.h | 80 +-
drivers/net/wireless/realtek/rtw88/pci.c | 84 +-
drivers/net/wireless/realtek/rtw88/pci.h | 4 -
drivers/net/wireless/realtek/rtw88/phy.c | 94 +-
drivers/net/wireless/realtek/rtw88/phy.h | 7 +
drivers/net/wireless/realtek/rtw88/reg.h | 108 +
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 2765 +++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 245 ++
.../wireless/realtek/rtw88/rtw8723d_table.c | 1196 +++++++
.../wireless/realtek/rtw88/rtw8723d_table.h | 15 +
.../net/wireless/realtek/rtw88/rtw8723de.c | 30 +
.../net/wireless/realtek/rtw88/rtw8723de.h | 20 +
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 33 +-
.../net/wireless/realtek/rtw88/rtw8822be.c | 30 +
.../net/wireless/realtek/rtw88/rtw8822be.h | 20 +
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 31 +
.../net/wireless/realtek/rtw88/rtw8822ce.c | 30 +
.../net/wireless/realtek/rtw88/rtw8822ce.h | 20 +
drivers/net/wireless/realtek/rtw88/rx.c | 1 +
drivers/net/wireless/realtek/rtw88/sec.c | 6 +-
drivers/net/wireless/realtek/rtw88/tx.c | 11 +-
drivers/net/wireless/realtek/rtw88/tx.h | 2 +-
drivers/net/wireless/realtek/rtw88/util.c | 20 +-
36 files changed, 5324 insertions(+), 198 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d_table.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723de.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723de.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822be.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822be.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822ce.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822ce.h

--
2.17.1


2020-04-17 07:49:05

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 02/40] rtw88: 8723d: add beamform wrapper functions

From: Ping-Ke Shih <[email protected]>

8723D doesn't support beamform because rtw88 only supports VHT beamform
but 8723d doesn't have VHT capability. Though 8723d doesn't support
beamform, BSS_CHANGED_MU_GROUPS is still marked as changed when doing
disassociation. So, add wrapper functions for all beamform ops to make
sure they aren't NULL before calling.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/bf.c | 7 +++---
drivers/net/wireless/realtek/rtw88/bf.h | 22 +++++++++++++++++++
drivers/net/wireless/realtek/rtw88/mac80211.c | 7 ++----
drivers/net/wireless/realtek/rtw88/main.c | 7 +++---
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 3 +++
5 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c
index b6d1d71f4d30..a5912da327e2 100644
--- a/drivers/net/wireless/realtek/rtw88/bf.c
+++ b/drivers/net/wireless/realtek/rtw88/bf.c
@@ -10,7 +10,6 @@
void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
- struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_bfee *bfee = &rtwvif->bfee;
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
@@ -23,7 +22,7 @@ void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
else if (bfee->role == RTW_BFEE_SU)
bfinfo->bfer_su_cnt--;

- chip->ops->config_bfee(rtwdev, rtwvif, bfee, false);
+ rtw_chip_config_bfee(rtwdev, rtwvif, bfee, false);

bfee->role = RTW_BFEE_NONE;
}
@@ -71,7 +70,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bfee->aid = bss_conf->aid;
bfinfo->bfer_mu_cnt++;

- chip->ops->config_bfee(rtwdev, rtwvif, bfee, true);
+ rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
} else if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
(vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) {
@@ -97,7 +96,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
}
}

- chip->ops->config_bfee(rtwdev, rtwvif, bfee, true);
+ rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
}

out_unlock:
diff --git a/drivers/net/wireless/realtek/rtw88/bf.h b/drivers/net/wireless/realtek/rtw88/bf.h
index 96a8216dd11f..17855edb5006 100644
--- a/drivers/net/wireless/realtek/rtw88/bf.h
+++ b/drivers/net/wireless/realtek/rtw88/bf.h
@@ -89,4 +89,26 @@ void rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
void rtw_bf_phy_init(struct rtw_dev *rtwdev);
void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
u8 fixrate_en, u8 *new_rate);
+static inline void rtw_chip_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+ struct rtw_bfee *bfee, bool enable)
+{
+ if (rtwdev->chip->ops->config_bfee)
+ rtwdev->chip->ops->config_bfee(rtwdev, vif, bfee, enable);
+}
+
+static inline void rtw_chip_set_gid_table(struct rtw_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf)
+{
+ if (rtwdev->chip->ops->set_gid_table)
+ rtwdev->chip->ops->set_gid_table(rtwdev, vif, conf);
+}
+
+static inline void rtw_chip_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
+ u8 fixrate_en, u8 *new_rate)
+{
+ if (rtwdev->chip->ops->cfg_csi_rate)
+ rtwdev->chip->ops->cfg_csi_rate(rtwdev, rssi, cur_rate,
+ fixrate_en, new_rate);
+}
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index a2e6ef4ad9ee..98d2ac22f6f6 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -375,11 +375,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON)
rtw_fw_download_rsvd_page(rtwdev);

- if (changed & BSS_CHANGED_MU_GROUPS) {
- struct rtw_chip_info *chip = rtwdev->chip;
-
- chip->ops->set_gid_table(rtwdev, vif, conf);
- }
+ if (changed & BSS_CHANGED_MU_GROUPS)
+ rtw_chip_set_gid_table(rtwdev, vif, conf);

if (changed & BSS_CHANGED_ERP_SLOT)
rtw_conf_tx(rtwdev, rtwvif);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 1e1d2c774287..6dfe4895c352 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -137,7 +137,6 @@ struct rtw_watch_dog_iter_data {
static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
{
struct rtw_bf_info *bf_info = &rtwdev->bf_info;
- struct rtw_chip_info *chip = rtwdev->chip;
u8 fix_rate_enable = 0;
u8 new_csi_rate_idx;

@@ -145,9 +144,9 @@ static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
rtwvif->bfee.role != RTW_BFEE_MU)
return;

- chip->ops->cfg_csi_rate(rtwdev, rtwdev->dm_info.min_rssi,
- bf_info->cur_csi_rpt_rate,
- fix_rate_enable, &new_csi_rate_idx);
+ rtw_chip_cfg_csi_rate(rtwdev, rtwdev->dm_info.min_rssi,
+ bf_info->cur_csi_rpt_rate,
+ fix_rate_enable, &new_csi_rate_idx);

if (new_csi_rate_idx != bf_info->cur_csi_rpt_rate)
bf_info->cur_csi_rpt_rate = new_csi_rate_idx;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index cccf05ee6807..5798a5804af3 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -16,6 +16,9 @@

static struct rtw_chip_ops rtw8723d_ops = {
.set_antenna = NULL,
+ .config_bfee = NULL,
+ .set_gid_table = NULL,
+ .cfg_csi_rate = NULL,
};

struct rtw_chip_info rtw8723d_hw_spec = {
--
2.17.1

2020-04-17 07:49:06

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 01/40] rtw88: 8723d: Add basic chip capabilities

From: Ping-Ke Shih <[email protected]>

RTL8723DE is an 11n 1x1 2.4G single band chip with the
following capabilities:

- TX/RX BD size: 16/8
- TX/RX desc size: 40/24
- physical/logical/protected efuse size: 512/512/96
- TX gain index factor: 1
- max TX power index: 0x3F
- band: 2G
- HT: support
- VHT: Not support

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/main.h | 2 +
drivers/net/wireless/realtek/rtw88/pci.c | 3 ++
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 44 +++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 8 ++++
.../wireless/realtek/rtw88/rtw8723d_table.c | 7 +++
.../wireless/realtek/rtw88/rtw8723d_table.h | 8 ++++
6 files changed, 72 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723d_table.h

diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index c9edcabd7c42..be74533320ad 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -41,6 +41,7 @@ extern unsigned int rtw_debug_mask;
extern const struct ieee80211_ops rtw_ops;
extern struct rtw_chip_info rtw8822b_hw_spec;
extern struct rtw_chip_info rtw8822c_hw_spec;
+extern struct rtw_chip_info rtw8723d_hw_spec;

#define RTW_MAX_CHANNEL_NUM_2G 14
#define RTW_MAX_CHANNEL_NUM_5G 49
@@ -183,6 +184,7 @@ enum rtw_wireless_set {
enum rtw_chip_type {
RTW_CHIP_TYPE_8822B,
RTW_CHIP_TYPE_8822C,
+ RTW_CHIP_TYPE_8723D,
};

enum rtw_tx_queue_type {
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index e37c71495c0d..b3e76b579af9 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1572,6 +1572,9 @@ static const struct pci_device_id rtw_pci_id_table[] = {
#endif
#ifdef CONFIG_RTW88_8822CE
{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822, rtw8822c_hw_spec) },
+#endif
+#ifdef CONFIG_RTW88_8723DE
+ { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723, rtw8723d_hw_spec) },
#endif
{},
};
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
new file mode 100644
index 000000000000..cccf05ee6807
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include "main.h"
+#include "coex.h"
+#include "fw.h"
+#include "tx.h"
+#include "rx.h"
+#include "phy.h"
+#include "rtw8723d.h"
+#include "rtw8723d_table.h"
+#include "mac.h"
+#include "reg.h"
+#include "debug.h"
+
+static struct rtw_chip_ops rtw8723d_ops = {
+ .set_antenna = NULL,
+};
+
+struct rtw_chip_info rtw8723d_hw_spec = {
+ .ops = &rtw8723d_ops,
+ .id = RTW_CHIP_TYPE_8723D,
+ .fw_name = "rtw88/rtw8723d_fw.bin",
+ .tx_pkt_desc_sz = 40,
+ .tx_buf_desc_sz = 16,
+ .rx_pkt_desc_sz = 24,
+ .rx_buf_desc_sz = 8,
+ .phy_efuse_size = 512,
+ .log_efuse_size = 512,
+ .ptct_efuse_size = 96 + 1,
+ .txgi_factor = 1,
+ .is_pwr_by_rate_dec = true,
+ .max_power_index = 0x3f,
+ .csi_buf_pg_num = 0,
+ .band = RTW_BAND_2G,
+ .ht_supported = true,
+ .vht_supported = false,
+ .lps_deep_mode_supported = 0,
+ .sys_func_en = 0xFD,
+};
+EXPORT_SYMBOL(rtw8723d_hw_spec);
+
+MODULE_FIRMWARE("rtw88/rtw8723d_fw.bin");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
new file mode 100644
index 000000000000..0b784cfc34c6
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW8723D_H__
+#define __RTW8723D_H__
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d_table.c b/drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
new file mode 100644
index 000000000000..b22b4b0f2fcf
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include "main.h"
+#include "phy.h"
+#include "rtw8723d_table.h"
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d_table.h b/drivers/net/wireless/realtek/rtw88/rtw8723d_table.h
new file mode 100644
index 000000000000..ea5933ffd043
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d_table.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW8723D_TABLE_H__
+#define __RTW8723D_TABLE_H__
+
+#endif
--
2.17.1

2020-04-17 07:49:38

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 24/40] rtw88: 8723d: add interface configurations table

From: Ping-Ke Shih <[email protected]>

Interface configuration table is used to configure PCI PHY that are
normally decided by design or bootstrap pin, and driver can do additional
settings by this table.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index dd8943426bb3..cf897af380c1 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -1072,6 +1072,26 @@ static const struct rtw_rqpn rqpn_table_8723d[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};

+static const struct rtw_intf_phy_para pcie_gen1_param_8723d[] = {
+ {0x0008, 0x4a22,
+ RTW_IP_SEL_PHY,
+ RTW_INTF_PHY_CUT_ALL,
+ RTW_INTF_PHY_PLATFORM_ALL},
+ {0x0009, 0x1000,
+ RTW_IP_SEL_PHY,
+ ~(RTW_INTF_PHY_CUT_A | RTW_INTF_PHY_CUT_B),
+ RTW_INTF_PHY_PLATFORM_ALL},
+ {0xFFFF, 0x0000,
+ RTW_IP_SEL_PHY,
+ RTW_INTF_PHY_CUT_ALL,
+ RTW_INTF_PHY_PLATFORM_ALL},
+};
+
+static const struct rtw_intf_phy_para_table phy_para_table_8723d = {
+ .gen1_para = pcie_gen1_param_8723d,
+ .n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8723d),
+};
+
static const struct rtw_hw_reg rtw8723d_dig[] = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xc50, .mask = 0x7f },
@@ -1122,6 +1142,7 @@ struct rtw_chip_info rtw8723d_hw_spec = {
.pwr_off_seq = card_disable_flow_8723d,
.page_table = page_table_8723d,
.rqpn_table = rqpn_table_8723d,
+ .intf_table = &phy_para_table_8723d,
.dig = rtw8723d_dig,
.dig_cck = rtw8723d_dig_cck,
.rf_sipi_addr = {0x840, 0x844},
--
2.17.1

2020-04-17 07:49:55

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 07/40] rtw88: 8723d: Add new chip op efuse_grant() to control efuse access

From: Ping-Ke Shih <[email protected]>

8723D devices need to grant efuse access before dumping physical efuse
map, other chips don't need it, so keep this ops as blank.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/efuse.c | 4 ++++
drivers/net/wireless/realtek/rtw88/main.h | 13 +++++++++++++
drivers/net/wireless/realtek/rtw88/reg.h | 9 +++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 13 +++++++++++++
4 files changed, 39 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c
index 212c8376a8c9..df969d346b41 100644
--- a/drivers/net/wireless/realtek/rtw88/efuse.c
+++ b/drivers/net/wireless/realtek/rtw88/efuse.c
@@ -90,6 +90,8 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
u32 addr;
u32 cnt;

+ rtw_chip_efuse_grant_on(rtwdev);
+
switch_efuse_bank(rtwdev);

/* disable 2.5V LDO */
@@ -113,6 +115,8 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
}

+ rtw_chip_efuse_grant_off(rtwdev);
+
return 0;
}

diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 8f15fc113af0..74302181da53 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -811,6 +811,7 @@ struct rtw_chip_ops {
u32 antenna_tx,
u32 antenna_rx);
void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
+ void (*efuse_grant)(struct rtw_dev *rtwdev, bool enable);
void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
void (*phy_calibration)(struct rtw_dev *rtwdev);
void (*dpk_track)(struct rtw_dev *rtwdev);
@@ -1712,6 +1713,18 @@ static inline bool rtw_ssid_equal(struct cfg80211_ssid *a,
return true;
}

+static inline void rtw_chip_efuse_grant_on(struct rtw_dev *rtwdev)
+{
+ if (rtwdev->chip->ops->efuse_grant)
+ rtwdev->chip->ops->efuse_grant(rtwdev, true);
+}
+
+static inline void rtw_chip_efuse_grant_off(struct rtw_dev *rtwdev)
+{
+ if (rtwdev->chip->ops->efuse_grant)
+ rtwdev->chip->ops->efuse_grant(rtwdev, false);
+}
+
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);
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 2afd547ebcc9..911d8e75db77 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -6,6 +6,7 @@
#define __RTW_REG_DEF_H__

#define REG_SYS_FUNC_EN 0x0002
+#define BIT_FEN_ELDR BIT(12)
#define BIT_FEN_CPUEN BIT(2)
#define BIT_FEN_BB_GLB_RST BIT(1)
#define BIT_FEN_BB_RSTB BIT(0)
@@ -15,6 +16,10 @@
#define REG_SYS_CLK_CTRL 0x0008
#define BIT_CPU_CLK_EN BIT(14)

+#define REG_SYS_CLKR 0x0008
+#define BIT_ANA8M BIT(1)
+#define BIT_LOADER_CLK_EN BIT(5)
+
#define REG_RSV_CTRL 0x001C
#define DISABLE_PI 0x3
#define ENABLE_PI 0x2
@@ -87,6 +92,10 @@
BIT_CHECK_SUM_OK)
#define FW_READY_MASK 0xffff

+#define REG_EFUSE_ACCESS 0x00CF
+#define EFUSE_ACCESS_ON 0x69
+#define EFUSE_ACCESS_OFF 0x00
+
#define REG_WLRF1 0x00EC
#define REG_WIFI_BT_INFO 0x00AA
#define BIT_BT_INT_EN BIT(15)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 04f8d73e4e6c..756454d69fad 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -28,11 +28,24 @@ static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}

+static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
+{
+ if (on) {
+ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+ rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
+ rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
+ } else {
+ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+ }
+}
+
static struct rtw_chip_ops rtw8723d_ops = {
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
.set_antenna = NULL,
.cfg_ldo25 = rtw8723d_cfg_ldo25,
+ .efuse_grant = rtw8723d_efuse_grant,
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
--
2.17.1

2020-04-17 07:50:02

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 22/40] rtw88: 8723d: Add chip_ops::false_alarm_statistics

From: Ping-Ke Shih <[email protected]>

This ops is used to do statistics of false alarm periodically, and then
fine tune RX initial gain to adaptive different circumstance.

There are three steps, hold/get/reset counter, to retrieve false alarm
counters that consist of CCK and OFDM. In addition to false alarm
counters, it also collects CRC ok/error counters of CCK, OFDM and HT.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 65 +++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 41 ++++++++++++
2 files changed, 106 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index c619ee289561..df78d3b4b07a 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -563,6 +563,70 @@ static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
}
}

+static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u32 cck_fa_cnt;
+ u32 ofdm_fa_cnt;
+ u32 crc32_cnt;
+ u32 val32;
+
+ /* hold counter */
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
+
+ cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
+ cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
+
+ val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
+ ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
+ ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
+ val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
+ dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
+ ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
+ val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
+ ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
+ ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
+ val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
+ ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
+
+ dm_info->cck_fa_cnt = cck_fa_cnt;
+ dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
+ dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
+
+ dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
+ dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
+ crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
+ dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
+ dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
+ crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
+ dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
+ dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
+ dm_info->vht_err_cnt = 0;
+ dm_info->vht_ok_cnt = 0;
+
+ val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
+ dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
+ u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
+ dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
+
+ /* reset counter */
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
+ rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
+ rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
+ rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
+ rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
+}
+
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
@@ -575,6 +639,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
.set_antenna = NULL,
.cfg_ldo25 = rtw8723d_cfg_ldo25,
.efuse_grant = rtw8723d_efuse_grant,
+ .false_alarm_statistics = rtw8723d_false_alarm_statistics,
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index c08c351ba657..b5b7fc9cd1c8 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -72,13 +72,54 @@ struct rtw8723d_efuse {
#define REG_FPGA1_RFMOD 0x0900
#define REG_BBRX_DFIR 0x0954
#define REG_CCK0_SYS 0x0a00
+#define REG_CCK_FA_RST_11N 0x0a2c
+#define BIT_MASK_CCK_CNT_KEEP BIT(12)
+#define BIT_MASK_CCK_CNT_EN BIT(13)
+#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
+#define BIT_MASK_CCK_FA_KEEP BIT(14)
+#define BIT_MASK_CCK_FA_EN BIT(15)
+#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
+#define REG_CCK_FA_LSB_11N 0x0a5c
+#define REG_CCK_FA_MSB_11N 0x0a58
+#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_OFDM_FA_HOLDC_11N 0x0c00
+#define BIT_MASK_OFDM_FA_KEEP BIT(31)
+#define REG_OFDM_FA_RSTC_11N 0x0c0c
+#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_OFDM0_RXDSP 0x0c40
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
+#define REG_OFDM_FA_TYPE1_11N 0x0cf0
+#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
+#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
+#define REG_OFDM_FA_RSTD_11N 0x0d00
+#define BIT_MASK_OFDM_FA_RST1 BIT(27)
+#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_OFDM1_CFOTRK 0x0d2c
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
+#define REG_OFDM_FA_TYPE2_11N 0x0da0
+#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
+#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
+#define REG_OFDM_FA_TYPE3_11N 0x0da4
+#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
+#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
+#define REG_OFDM_FA_TYPE4_11N 0x0da8
+#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
+#define REG_PAGE_F_RST_11N 0x0f14
+#define BIT_MASK_F_RST_ALL BIT(16)
+#define REG_IGI_C_11N 0x0f84
+#define REG_IGI_D_11N 0x0f88
+#define REG_HT_CRC32_CNT_11N 0x0f90
+#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
+#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
+#define REG_OFDM_CRC32_CNT_11N 0x0f94
+#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
+#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
+#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8

#endif
--
2.17.1

2020-04-17 07:50:09

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 38/40] rtw88: extract: make 8723d an individual kernel module

From: Zong-Zhe Yang <[email protected]>

Make objects about 8723d functions and 8723d tables,
i.e. rtw8723d.o and rtw8723d_table.o, an individual
kernel module called rtw88_8723d.ko.

For 8723d pcie chip, i.e. 8723DE chip, add a chip
entry point module called rtw88_8723de.ko which
will depend on rtw88_8723d.ko and rtwpci.ko.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/Kconfig | 6 +++-
drivers/net/wireless/realtek/rtw88/Makefile | 7 ++++-
drivers/net/wireless/realtek/rtw88/main.h | 1 -
drivers/net/wireless/realtek/rtw88/pci.c | 3 --
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 5 ++++
.../net/wireless/realtek/rtw88/rtw8723de.c | 30 +++++++++++++++++++
.../net/wireless/realtek/rtw88/rtw8723de.h | 20 +++++++++++++
7 files changed, 66 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723de.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723de.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index dd71407a06c3..ca894c4f96ac 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -22,6 +22,9 @@ config RTW88_8822B
config RTW88_8822C
tristate

+config RTW88_8723D
+ tristate
+
config RTW88_8822BE
tristate "Realtek 8822BE PCI wireless network adapter"
depends on PCI
@@ -45,10 +48,11 @@ config RTW88_8822CE
802.11ac PCIe wireless network adapter

config RTW88_8723DE
- bool "Realtek 8723DE PCI wireless network adapter"
+ tristate "Realtek 8723DE PCI wireless network adapter"
depends on PCI
select RTW88_CORE
select RTW88_PCI
+ select RTW88_8723D
help
Select this option will enable support for 8723DE chipset

diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 0b29f07e3661..9e3e95360089 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -18,7 +18,6 @@ rtw88-y += main.o \
wow.o \
regd.o

-rtw88-$(CONFIG_RTW88_8723DE) += rtw8723d.o rtw8723d_table.o

obj-$(CONFIG_RTW88_8822B) += rtw88_8822b.o
rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
@@ -32,5 +31,11 @@ rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o
obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o
rtw88_8822ce-objs := rtw8822ce.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_PCI) += rtwpci.o
rtwpci-objs := pci.o
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index a0c34c1154b6..7c785a63fadf 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -39,7 +39,6 @@ extern bool rtw_bf_support;
extern unsigned int rtw_fw_lps_deep_mode;
extern unsigned int rtw_debug_mask;
extern const struct ieee80211_ops rtw_ops;
-extern struct rtw_chip_info rtw8723d_hw_spec;

#define RTW_MAX_CHANNEL_NUM_2G 14
#define RTW_MAX_CHANNEL_NUM_5G 49
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 25672d0a09aa..46aaac94287b 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1598,9 +1598,6 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
EXPORT_SYMBOL(rtw_pci_shutdown);

static const struct pci_device_id rtw_pci_id_table[] = {
-#ifdef CONFIG_RTW88_8723DE
- { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723, rtw8723d_hw_spec) },
-#endif
{},
};
MODULE_DEVICE_TABLE(pci, rtw_pci_id_table);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 5a662112752d..5c592560c3e0 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2018-2019 Realtek Corporation
*/

+#include <linux/module.h>
#include "main.h"
#include "coex.h"
#include "fw.h"
@@ -2758,3 +2759,7 @@ struct rtw_chip_info rtw8723d_hw_spec = {
EXPORT_SYMBOL(rtw8723d_hw_spec);

MODULE_FIRMWARE("rtw88/rtw8723d_fw.bin");
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723d driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c
new file mode 100644
index 000000000000..105866eb0a55
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "rtw8723de.h"
+
+static const struct pci_device_id rtw_8723de_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723),
+ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(pci, rtw_8723de_id_table);
+
+static struct pci_driver rtw_8723de_driver = {
+ .name = "rtw_8723de",
+ .id_table = rtw_8723de_id_table,
+ .probe = rtw_pci_probe,
+ .remove = rtw_pci_remove,
+ .driver.pm = RTW_PM_OPS,
+ .shutdown = rtw_pci_shutdown,
+};
+module_pci_driver(rtw_8723de_driver);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723de driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.h b/drivers/net/wireless/realtek/rtw88/rtw8723de.h
new file mode 100644
index 000000000000..fbf5b9bcd314
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_8723DE_H_
+#define __RTW_8723DE_H_
+
+#ifdef CONFIG_PM
+extern const struct dev_pm_ops rtw_pci_pm;
+#define RTW_PM_OPS (&rtw_pci_pm)
+#else
+#define RTW_PM_OPS NULL
+#endif
+
+extern struct rtw_chip_info rtw8723d_hw_spec;
+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);
+
+#endif
--
2.17.1

2020-04-17 07:50:29

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 19/40] rtw88: 8723d: Add set_channel

From: Ping-Ke Shih <[email protected]>

Set MAC/BB/RF register according to specified channel. The function
rtw_set_channel_mac() is used to set MAC registers, but 8723D only need
some of them.

For channel 14, we need to set different CCK DFIR values, so restore the
values when channel 1 to 13 is selected.

Spur calibration is needed in channel 13 and 14, and we do notch if spur
is over threshold.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/mac.c | 3 +
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 185 ++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 12 ++
3 files changed, 200 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index 645207a01525..c42d0f681dda 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -40,6 +40,9 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
}
rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32);

+ if (rtw_chip_wcpu_11n(rtwdev))
+ return;
+
value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL);
value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
rtw_write32(rtwdev, REG_AFE_CTRL1, value32);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 653cfa9445fc..c619ee289561 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -287,6 +287,190 @@ static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
}

+static
+bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev, u8 channel, u32 thres)
+{
+#define DIS_3WIRE 0xccf000c0
+#define EN_3WIRE 0xccc000c0
+#define START_PSD 0x400000
+#define FREQ_CH13 0xFCCD
+#define FREQ_CH14 0xFF9A
+
+ u32 freq;
+ bool ret = false;
+
+ if (channel == 13)
+ freq = FREQ_CH13;
+ else if (channel == 14)
+ freq = FREQ_CH14;
+ else
+ return false;
+
+ rtw_write32(rtwdev, REG_ANALOG_P4, DIS_3WIRE);
+ rtw_write32(rtwdev, REG_PSDFN, freq);
+ rtw_write32(rtwdev, REG_PSDFN, START_PSD | freq);
+
+ msleep(30);
+ if (rtw_read32(rtwdev, REG_PSDRPT) >= thres)
+ ret = true;
+
+ rtw_write32(rtwdev, REG_PSDFN, freq);
+ rtw_write32(rtwdev, REG_ANALOG_P4, EN_3WIRE);
+
+ return ret;
+}
+
+static void rtw8723d_cfg_notch(struct rtw_dev *rtwdev, u8 channel, bool notch)
+{
+#define BIT_MASK_RXDSP (BIT(28) | BIT(27) | BIT(26) | BIT(25) | BIT(24))
+#define BIT_EN_RXDSP BIT(9)
+#define BIT_EN_CFOTRK BIT(28)
+
+ if (!notch)
+ goto no_notch;
+
+ switch (channel) {
+ case 13:
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0xB);
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+ rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x04000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+ rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+ break;
+ case 14:
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x5);
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+ rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00080000);
+ rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+ break;
+ default:
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+ rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+ break;
+ }
+
+ return;
+
+no_notch:
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x1f);
+ rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+ rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+ rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+ rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+}
+
+static void rtw8723d_spur_cal(struct rtw_dev *rtwdev, u8 channel)
+{
+#define SPUR_THRES 0x16
+ bool notch = false;
+
+ if (channel < 13)
+ goto do_notch;
+
+ notch = rtw8723d_check_spur_ov_thres(rtwdev, channel, SPUR_THRES);
+
+do_notch:
+ rtw8723d_cfg_notch(rtwdev, channel, notch);
+}
+
+static void rtw8723d_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
+#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
+#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
+#define RFCFGCH_BW_40M (BIT(10))
+
+ u32 rf_cfgch[2];
+
+ rf_cfgch[0] = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+ rf_cfgch[1] = rtw_read_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK);
+
+ rf_cfgch[0] &= ~RFCFGCH_CHANNEL_MASK;
+ rf_cfgch[1] &= ~RFCFGCH_CHANNEL_MASK;
+ rf_cfgch[0] |= (channel & RFCFGCH_CHANNEL_MASK);
+ rf_cfgch[1] |= (channel & RFCFGCH_CHANNEL_MASK);
+
+ rf_cfgch[0] &= ~RFCFGCH_BW_MASK;
+ switch (bw) {
+ case RTW_CHANNEL_WIDTH_20:
+ rf_cfgch[0] |= RFCFGCH_BW_20M;
+ break;
+ case RTW_CHANNEL_WIDTH_40:
+ rf_cfgch[0] |= RFCFGCH_BW_40M;
+ break;
+ default:
+ break;
+ }
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_cfgch[0]);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_cfgch[1]);
+
+ rtw8723d_spur_cal(rtwdev, channel);
+}
+
+#define CCK_DFIR_NR 3
+static const struct rtw_backup_info cck_dfir_cfg[][CCK_DFIR_NR] = {
+ [0] = {
+ { .len = 4, .reg = 0xA24, .val = 0x64B80C1C },
+ { .len = 4, .reg = 0xA28, .val = 0x00008810 },
+ { .len = 4, .reg = 0xAAC, .val = 0x01235667 },
+ },
+ [1] = {
+ { .len = 4, .reg = 0xA24, .val = 0x0000B81C },
+ { .len = 4, .reg = 0xA28, .val = 0x00000000 },
+ { .len = 4, .reg = 0xAAC, .val = 0x00003667 },
+ },
+};
+
+static void rtw8723d_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+ u8 primary_ch_idx)
+{
+#define BIT_CCK_SIDE_BAND BIT(4)
+#define BIT_MASK_RFMOD BIT(0)
+#define BIT_RXBB_DFIR_EN BIT(19)
+#define BIT_MASK_RXBB_DFIR (BIT(27) | BIT(26) | BIT(25) | BIT(24))
+
+ const struct rtw_backup_info *cck_dfir =
+ channel <= 13 ? cck_dfir_cfg[0] : cck_dfir_cfg[1];
+ int i;
+
+ for (i = 0; i < CCK_DFIR_NR; i++, cck_dfir++)
+ rtw_write32(rtwdev, cck_dfir->reg, cck_dfir->val);
+
+ switch (bw) {
+ case RTW_CHANNEL_WIDTH_20:
+ rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x0);
+ rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x0);
+ rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 1);
+ rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_MASK_RXBB_DFIR, 0xa);
+ break;
+ case RTW_CHANNEL_WIDTH_40:
+ rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x1);
+ rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x1);
+ rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 0);
+ rtw_write32_mask(rtwdev, REG_CCK0_SYS, BIT_CCK_SIDE_BAND,
+ (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0));
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw8723d_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+ u8 primary_chan_idx)
+{
+ rtw8723d_set_channel_rf(rtwdev, channel, bw);
+ rtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx);
+ rtw8723d_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);
+}
+
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
@@ -383,6 +567,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
.query_rx_desc = rtw8723d_query_rx_desc,
+ .set_channel = rtw8723d_set_channel,
.mac_init = rtw8723d_mac_init,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 035049a29e7c..c08c351ba657 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -66,7 +66,19 @@ struct rtw8723d_efuse {
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))

+#define REG_PSDFN 0x0808
+#define REG_ANALOG_P4 0x088c
+#define REG_PSDRPT 0x08b4
+#define REG_FPGA1_RFMOD 0x0900
+#define REG_BBRX_DFIR 0x0954
+#define REG_CCK0_SYS 0x0a00
+#define REG_OFDM0_RXDSP 0x0c40
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
+#define REG_OFDM1_CFOTRK 0x0d2c
+#define REG_OFDM1_CSI1 0x0d40
+#define REG_OFDM1_CSI2 0x0d44
+#define REG_OFDM1_CSI3 0x0d48
+#define REG_OFDM1_CSI4 0x0d4c

#endif
--
2.17.1

2020-04-17 07:50:29

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 18/40] rtw88: 8723d: Add query_rx_desc

From: Ping-Ke Shih <[email protected]>

This ops is used to parse RX descriptor to know the length of received
packet and containing PHY status. If PHY status is existing, the order is
RX descriptor, PHY status and then packet.

There are two types of PHY status, named CCK and OFDM. Their size are the
same, but formats are different.

struct ieee80211_rx_status is also filled depends on above information.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 116 ++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 22 ++++
2 files changed, 138 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 52afa72caf8f..653cfa9445fc 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -172,6 +172,121 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
return 0;
}

+static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ s8 min_rx_power = -120;
+ u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
+
+ pkt_stat->rx_power[RF_PATH_A] = pwdb - 97;
+ pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
+ pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
+ pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
+ min_rx_power);
+ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
+}
+
+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;
+ s8 rx_evm;
+
+ if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
+ rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
+ else
+ rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status);
+
+ if (GET_PHY_STAT_P1_RF_MODE(phy_status) == 0)
+ bw = RTW_CHANNEL_WIDTH_20;
+ else if ((rxsc == 1) || (rxsc == 2))
+ bw = RTW_CHANNEL_WIDTH_20;
+ else
+ bw = RTW_CHANNEL_WIDTH_40;
+
+ 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);
+ pkt_stat->bw = bw;
+ pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
+ min_rx_power);
+ pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
+ pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
+ pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
+
+ dm_info->curr_rx_rate = pkt_stat->rate;
+ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
+ dm_info->rx_snr[RF_PATH_A] = pkt_stat->rx_snr[RF_PATH_A] >> 1;
+ dm_info->cfo_tail[RF_PATH_A] = (pkt_stat->cfo_tail[RF_PATH_A] * 5) >> 1;
+
+ rx_evm = clamp_t(s8, -pkt_stat->rx_evm[RF_PATH_A] >> 1, 0, 64);
+ rx_evm &= 0x3F; /* 64->0: second path of 1SS rate is 64 */
+ dm_info->rx_evm_dbm[RF_PATH_A] = rx_evm;
+}
+
+static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat)
+{
+ u8 page;
+
+ page = *phy_status & 0xf;
+
+ switch (page) {
+ case 0:
+ query_phy_status_page0(rtwdev, phy_status, pkt_stat);
+ break;
+ case 1:
+ query_phy_status_page1(rtwdev, phy_status, pkt_stat);
+ break;
+ default:
+ rtw_warn(rtwdev, "unused phy status page (%d)\n", page);
+ return;
+ }
+}
+
+static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_rx_status *rx_status)
+{
+ struct ieee80211_hdr *hdr;
+ u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+ u8 *phy_status = NULL;
+
+ memset(pkt_stat, 0, sizeof(*pkt_stat));
+
+ 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) &&
+ 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);
+ pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+ pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+ pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+ pkt_stat->ppdu_cnt = 0;
+ pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+
+ /* drv_info_sz is in unit of 8-bytes */
+ pkt_stat->drv_info_sz *= 8;
+
+ /* c2h cmd pkt's rx/phy status is not interested */
+ if (pkt_stat->is_c2h)
+ return;
+
+ hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+ pkt_stat->drv_info_sz);
+ if (pkt_stat->phy_status) {
+ phy_status = rx_desc + desc_sz + pkt_stat->shift;
+ query_phy_status(rtwdev, phy_status, pkt_stat);
+ }
+
+ rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+}
+
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
@@ -267,6 +382,7 @@ static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
+ .query_rx_desc = rtw8723d_query_rx_desc,
.mac_init = rtw8723d_mac_init,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 6321dea83519..035049a29e7c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -44,6 +44,28 @@ struct rtw8723d_efuse {
struct rtw8723de_efuse e;
};

+/* phy status page0 */
+#define GET_PHY_STAT_P0_PWDB(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
+
+/* phy status page1 */
+#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
+#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
+#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
+ 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_RXEVM_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
+
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58

--
2.17.1

2020-04-17 07:50:30

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 26/40] rtw88: 8723d: add IQ calibration

From: Ping-Ke Shih <[email protected]>

IQ calibration is used to calibrate RF characteristic to yield expected
performance. Basically, we do calibration twice and compare the similarity
to determine calibration is good or not, if not we do the third
calibration, and then compare with the results of first and second
calibration. If it still not similar, IQK is failed.

Before doing calibration, we need to backup registers that will be
modified in calibration procedure, and restore these registers after
calibration is done.

A calibration procedure can divided into four sub-procedures that are
S1-TX, S1-RX, S0-TX and S0-RX. Where, S1 and S0 represent to path A and B
respectively. Each sub-procedure configure proper registers, and then
rigger one-shot calibration and poll until completion. For RX calibration,
it needs to do twice one-shot calibration, first one is to yield parameter
used by second one.

The result of TX part is stored for TX power tracking that adjusts TX AGC
to output expected power.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/main.h | 12 +
drivers/net/wireless/realtek/rtw88/phy.c | 2 +
drivers/net/wireless/realtek/rtw88/reg.h | 10 +
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 830 ++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 112 +++
5 files changed, 966 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index d51eeda3627c..e0345b00dccb 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1397,6 +1397,16 @@ struct rtw_pkt_count {
DECLARE_EWMA(evm, 10, 4);
DECLARE_EWMA(snr, 10, 4);

+struct rtw_iqk_info {
+ bool done;
+ struct {
+ u32 s1_x;
+ u32 s1_y;
+ u32 s0_x;
+ u32 s0_y;
+ } result;
+};
+
struct rtw_dm_info {
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
@@ -1456,6 +1466,8 @@ struct rtw_dm_info {
struct rtw_pkt_count last_pkt_count;
struct ewma_evm ewma_evm[RTW_EVM_NUM];
struct ewma_snr ewma_snr[RTW_SNR_NUM];
+
+ struct rtw_iqk_info iqk;
};

struct rtw_efuse {
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index 72a16eff9db3..837b7bd04126 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -134,6 +134,8 @@ void rtw_phy_init(struct rtw_dev *rtwdev)
mask = chip->dig[0].mask;
dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask);
rtw_phy_cck_pd_init(rtwdev);
+
+ dm_info->iqk.done = false;
}

void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 9fdfcdc5c5cf..d57de1a6cdcc 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -69,6 +69,7 @@
#define BIT_DPDT_SEL_EN BIT(23)
#define REG_LEDCFG2 0x004E
#define REG_PAD_CTRL1 0x0064
+#define BIT_BT_BTG_SEL BIT(31)
#define BIT_PAPE_WLBT_SEL BIT(29)
#define BIT_LNAON_WLBT_SEL BIT(28)
#define BIT_BTGP_JTAG_EN BIT(24)
@@ -611,7 +612,10 @@

#define REG_IGN_GNTBT4 0x4160

+#define RF_MODE 0x00
#define RF_MODOPT 0x01
+#define RF_WLINT 0x01
+#define RF_WLSEL 0x02
#define RF_DTXLOK 0x08
#define RF_CFGCH 0x18
#define RF_RCK 0x1d
@@ -619,9 +623,15 @@
#define RF_LUTWD1 0x3e
#define RF_LUTWD0 0x3f
#define RF_T_METER 0x42
+#define RF_BSPAD 0x54
+#define RF_GAINTX 0x56
+#define RF_TXATANK 0x64
+#define RF_TRXIQ 0x66
+#define RF_RXIQGEN 0x8d
#define RF_XTALX2 0xb8
#define RF_MALSEL 0xbe
#define RF_RCKD 0xde
+#define RF_TXADBG 0xde
#define RF_LUTDBG 0xdf
#define RF_LUTWE2 0xee
#define RF_LUTWE 0xef
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 94784c7f0743..b66bd969e007 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -657,6 +657,835 @@ static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev)
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
}

+#define MAX_TOLERANCE 5
+#define IQK_TX_X_ERR 0x142
+#define IQK_TX_Y_ERR 0x42
+#define IQK_RX_X_UPPER 0x11a
+#define IQK_RX_X_LOWER 0xe6
+#define IQK_RX_Y_LMT 0x1a
+
+static const u32 iqk_adda_regs[] = {
+ 0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
+ 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
+};
+
+static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551};
+static const u32 iqk_mac32_regs[] = {0x40};
+
+static const u32 iqk_bb_regs[] = {
+ 0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
+};
+
+#define IQK_ADDA_REG_NUM ARRAY_SIZE(iqk_adda_regs)
+#define IQK_MAC8_REG_NUM ARRAY_SIZE(iqk_mac8_regs)
+#define IQK_MAC32_REG_NUM ARRAY_SIZE(iqk_mac32_regs)
+#define IQK_BB_REG_NUM ARRAY_SIZE(iqk_bb_regs)
+
+struct iqk_backup_regs {
+ u32 adda[IQK_ADDA_REG_NUM];
+ u8 mac8[IQK_MAC8_REG_NUM];
+ u32 mac32[IQK_MAC32_REG_NUM];
+ u32 bb[IQK_BB_REG_NUM];
+
+ u32 lte_path;
+ u32 lte_gnt;
+
+ u8 btg_sel;
+ u32 bb_sel_btg;
+
+ u8 igia;
+ u8 igib;
+};
+
+static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
+ struct iqk_backup_regs *backup)
+{
+ int i;
+
+ for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+ backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
+
+ for (i = 0; i < IQK_MAC8_REG_NUM; i++)
+ backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
+ for (i = 0; i < IQK_MAC32_REG_NUM; i++)
+ backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
+
+ for (i = 0; i < IQK_BB_REG_NUM; i++)
+ backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
+
+ backup->igia = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
+ backup->igib = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
+
+ backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
+}
+
+static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev,
+ const struct iqk_backup_regs *backup)
+{
+ int i;
+
+ for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+ rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]);
+
+ for (i = 0; i < IQK_MAC8_REG_NUM; i++)
+ rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]);
+ for (i = 0; i < IQK_MAC32_REG_NUM; i++)
+ rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]);
+
+ for (i = 0; i < IQK_BB_REG_NUM; i++)
+ rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]);
+
+ rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
+ rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
+
+ rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
+ rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
+
+ rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
+ rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
+}
+
+static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
+ struct iqk_backup_regs *backup)
+{
+ backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
+ backup->btg_sel);
+}
+
+static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
+{
+ rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
+ rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+}
+
+static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
+ const struct iqk_backup_regs *backup)
+{
+ rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
+ rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+}
+
+static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
+ struct iqk_backup_regs *backup)
+{
+ backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
+ rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
+ mdelay(1);
+ backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
+ backup->lte_gnt);
+}
+
+static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev)
+{
+ rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00);
+ rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
+ rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1);
+}
+
+static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
+ const struct iqk_backup_regs *bak)
+{
+ rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
+ rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
+ rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
+}
+
+struct rtw_8723d_iqk_cfg {
+ const char *name;
+ u32 val_bb_sel_btg;
+ u32 reg_lutwe;
+ u32 val_txiqk_pi;
+ u32 reg_padlut;
+ u32 reg_gaintx;
+ u32 reg_bspad;
+ u32 val_wlint;
+ u32 val_wlsel;
+ u32 val_iqkpts;
+};
+
+static const struct rtw_8723d_iqk_cfg iqk_tx_cfg[PATH_NR] = {
+ [PATH_S1] = {
+ .name = "S1",
+ .val_bb_sel_btg = 0x99000000,
+ .reg_lutwe = RF_LUTWE,
+ .val_txiqk_pi = 0x8214019f,
+ .reg_padlut = RF_LUTDBG,
+ .reg_gaintx = RF_GAINTX,
+ .reg_bspad = RF_BSPAD,
+ .val_wlint = 0xe0d,
+ .val_wlsel = 0x60d,
+ .val_iqkpts = 0xfa000000,
+ },
+ [PATH_S0] = {
+ .name = "S0",
+ .val_bb_sel_btg = 0x99000280,
+ .reg_lutwe = RF_LUTWE2,
+ .val_txiqk_pi = 0x8214018a,
+ .reg_padlut = RF_TXADBG,
+ .reg_gaintx = RF_TRXIQ,
+ .reg_bspad = RF_TXATANK,
+ .val_wlint = 0xe6d,
+ .val_wlsel = 0x66d,
+ .val_iqkpts = 0xf9000000,
+ },
+};
+
+enum {
+ IQK_TX_OK = BIT(0),
+ IQK_RX_OK = BIT(1),
+};
+
+static u8 rtw8723d_iqk_check_tx_failed(struct rtw_dev *rtwdev,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+ s32 tx_x, tx_y;
+ u32 tx_fail;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xeac = 0x%x\n",
+ rtw_read32(rtwdev, REG_IQK_RES_RY));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe94 = 0x%x, 0xe9c = 0x%x\n",
+ rtw_read32(rtwdev, REG_IQK_RES_TX),
+ rtw_read32(rtwdev, REG_IQK_RES_TY));
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] 0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+ rtw_read32(rtwdev, 0xe90),
+ rtw_read32(rtwdev, 0xe98));
+
+ tx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_TX_FAIL);
+ tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+ tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+
+ if (!tx_fail && tx_x != IQK_TX_X_ERR && tx_y != IQK_TX_Y_ERR)
+ return IQK_TX_OK;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s TXIQK is failed\n",
+ iqk_cfg->name);
+
+ return 0;
+}
+
+static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+ s32 rx_x, rx_y;
+ u32 rx_fail;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xea4 = 0x%x, 0xeac = 0x%x\n",
+ rtw_read32(rtwdev, REG_IQK_RES_RX),
+ rtw_read32(rtwdev, REG_IQK_RES_RY));
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] 0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n",
+ rtw_read32(rtwdev, 0xea0),
+ rtw_read32(rtwdev, 0xea8));
+
+ rx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_RX_FAIL);
+ rx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+ rx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+ rx_y = abs(iqkxy_to_s32(rx_y));
+
+ if (!rx_fail && rx_x < IQK_RX_X_UPPER && rx_x > IQK_RX_X_LOWER &&
+ rx_y < IQK_RX_Y_LMT)
+ return IQK_RX_OK;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s RXIQK STEP2 is failed\n",
+ iqk_cfg->name);
+
+ return 0;
+}
+
+static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+ u32 pts = (tx ? iqk_cfg->val_iqkpts : 0xf9000000);
+
+ /* enter IQK mode */
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+ rtw8723d_iqk_config_lte_path_gnt(rtwdev);
+
+ rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054);
+ mdelay(1);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] GNT_BT @%s %sIQK1 = 0x%x\n",
+ iqk_cfg->name, tx ? "TX" : "RX",
+ rtw_read32(rtwdev, REG_LTECOEX_READ_DATA));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x948 @%s %sIQK1 = 0x%x\n",
+ iqk_cfg->name, tx ? "TX" : "RX",
+ rtw_read32(rtwdev, REG_BB_SEL_BTG));
+
+ /* One shot, LOK & IQK */
+ rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, pts);
+ rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, 0xf8000000);
+
+ if (!check_hw_ready(rtwdev, REG_IQK_RES_RY, BIT_IQK_DONE, 1))
+ rtw_warn(rtwdev, "%s %s IQK isn't done\n", iqk_cfg->name,
+ tx ? "TX" : "RX");
+}
+
+static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg,
+ const struct iqk_backup_regs *backup)
+{
+ rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup);
+ rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg);
+
+ /* leave IQK mode */
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+ mdelay(1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, BIT(0), 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, BIT(0), 0x0);
+}
+
+static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg,
+ const struct iqk_backup_regs *backup)
+{
+ u8 result = 0x00;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s TXIQK!!\n", iqk_cfg->name);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s TXIQK = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+
+ rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg);
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+ mdelay(1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00004);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005d);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xBFFE0);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+ /* IQK setting */
+ rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x08008c0c);
+ rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c);
+ rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, iqk_cfg->val_txiqk_pi);
+ rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160200);
+ rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+ rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+ /* LOK setting */
+ rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x00462911);
+
+ /* PA, PAD setting */
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x1E0, 0x3);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXIQGEN, 0x1F, 0xf);
+
+ /* LOK setting for 8723D */
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x10, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_bspad, 0x1, 0x1);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s TXIQK = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s TXIQK = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+ rtw8723d_iqk_one_shot(rtwdev, true, iqk_cfg);
+ result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
+
+ rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
+
+ return result;
+}
+
+static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
+ const struct rtw_8723d_iqk_cfg *iqk_cfg,
+ const struct iqk_backup_regs *backup)
+{
+ u32 tx_x, tx_y;
+ u8 result = 0x00;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK Step1!!\n",
+ iqk_cfg->name);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK1 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+ rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg);
+
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+
+ /* IQK setting */
+ rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+ rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+ /* path IQK setting */
+ rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x18008c1c);
+ rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c);
+ rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c);
+ rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82160000);
+ rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160000);
+
+ /* LOK setting */
+ rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a911);
+
+ /* RXIQK mode */
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00006);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xa7ffb);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+ /* PA/PAD=0 */
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1@ path %s RXIQK1 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2@ path %s RXIQK1 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+ rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
+ result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
+
+ if (!result)
+ goto restore;
+
+ tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+ tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+
+ rtw_write32(rtwdev, REG_TXIQK_11N, BIT_SET_TXIQK_11N(tx_x, tx_y));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe40 = 0x%x u4tmp = 0x%x\n",
+ rtw_read32(rtwdev, REG_TXIQK_11N),
+ BIT_SET_TXIQK_11N(tx_x, tx_y));
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK STEP2!!\n",
+ iqk_cfg->name);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK2 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+
+ rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+ rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x38008c1c);
+ rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x18008c1c);
+ rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c);
+ rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82170000);
+ rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28171400);
+
+ /* LOK setting */
+ rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a8d1);
+
+ /* RXIQK mode */
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+ mdelay(1);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x80000, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00007);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xb3fdb);
+ rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s RXIQK2 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s RXIQK2 = 0x%x\n",
+ iqk_cfg->name,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+ rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
+ result |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg);
+
+restore:
+ rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
+
+ return result;
+}
+
+static
+void rtw8723d_iqk_fill_s1_matrix(struct rtw_dev *rtwdev, const s32 result[])
+{
+ s32 oldval_1;
+ s32 x, y;
+ s32 tx1_a, tx1_a_ext;
+ s32 tx1_c, tx1_c_ext;
+
+ if (result[IQK_S1_TX_X] == 0)
+ return;
+
+ oldval_1 = rtw_read32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+ BIT_MASK_TXIQ_ELM_D);
+
+ x = iqkxy_to_s32(result[IQK_S1_TX_X]);
+ tx1_a = iqk_mult(x, oldval_1, &tx1_a_ext);
+ rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+ BIT_MASK_TXIQ_ELM_A, tx1_a);
+ rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD,
+ BIT_MASK_OFDM0_EXT_A, tx1_a_ext);
+
+ y = iqkxy_to_s32(result[IQK_S1_TX_Y]);
+ tx1_c = iqk_mult(y, oldval_1, &tx1_c_ext);
+ rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS,
+ BIT_SET_TXIQ_ELM_C1(tx1_c));
+ rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+ BIT_MASK_TXIQ_ELM_C, BIT_SET_TXIQ_ELM_C2(tx1_c));
+ rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD,
+ BIT_MASK_OFDM0_EXT_C, tx1_c_ext);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] X = 0x%x, TX1_A = 0x%x, oldval_1 0x%x\n",
+ x, tx1_a, oldval_1);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] Y = 0x%x, TX1_C = 0x%x\n", y, tx1_c);
+
+ if (result[IQK_S1_RX_X] == 0)
+ return;
+
+ rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_X,
+ result[IQK_S1_RX_X]);
+ rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_Y1,
+ BIT_SET_RXIQ_S1_Y1(result[IQK_S1_RX_Y]));
+ rtw_write32_mask(rtwdev, REG_RXIQK_MATRIX_LSB_11N, BIT_MASK_RXIQ_S1_Y2,
+ BIT_SET_RXIQ_S1_Y2(result[IQK_S1_RX_Y]));
+}
+
+static
+void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[])
+{
+ s32 oldval_0;
+ s32 x, y;
+ s32 tx0_a, tx0_a_ext;
+ s32 tx0_c, tx0_c_ext;
+
+ if (result[IQK_S0_TX_X] == 0)
+ return;
+
+ oldval_0 = rtw_read32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0);
+
+ x = iqkxy_to_s32(result[IQK_S0_TX_X]);
+ tx0_a = iqk_mult(x, oldval_0, &tx0_a_ext);
+
+ rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, tx0_a);
+ rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, tx0_a_ext);
+
+ y = iqkxy_to_s32(result[IQK_S0_TX_Y]);
+ tx0_c = iqk_mult(y, oldval_0, &tx0_c_ext);
+
+ rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, tx0_c);
+ rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, tx0_c_ext);
+
+ if (result[IQK_S0_RX_X] == 0)
+ return;
+
+ rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_X_S0,
+ result[IQK_S0_RX_X]);
+ rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_Y_S0,
+ result[IQK_S0_RX_Y]);
+}
+
+static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev)
+{
+ int i;
+
+ for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+ rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016);
+}
+
+static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev)
+{
+ rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
+}
+
+static
+void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path)
+{
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path-%s standby mode!\n",
+ path == RF_PATH_A ? "S1" : "S0");
+
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+ mdelay(1);
+ rtw_write_rf(rtwdev, path, RF_MODE, RFREG_MASK, 0x10000);
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+}
+
+static
+bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
+ u8 c1, u8 c2)
+{
+ u32 i, j, diff;
+ u32 bitmap = 0;
+ u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
+ bool ret = true;
+
+ s32 tmp1, tmp2;
+
+ for (i = 0; i < IQK_NR; i++) {
+ tmp1 = iqkxy_to_s32(result[c1][i]);
+ tmp2 = iqkxy_to_s32(result[c2][i]);
+
+ diff = abs(tmp1 - tmp2);
+
+ if (diff <= MAX_TOLERANCE)
+ continue;
+
+ if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
+ if (result[c1][i] + result[c1][i + 1] == 0)
+ candidate[i / IQK_SX_NR] = c2;
+ else if (result[c2][i] + result[c2][i + 1] == 0)
+ candidate[i / IQK_SX_NR] = c1;
+ else
+ bitmap |= BIT(i);
+ } else {
+ bitmap |= BIT(i);
+ }
+ }
+
+ if (bitmap != 0)
+ goto check_sim;
+
+ for (i = 0; i < PATH_NR; i++) {
+ if (candidate[i] == IQK_ROUND_INVALID)
+ continue;
+
+ for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
+ result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
+ ret = false;
+ }
+
+ return ret;
+
+check_sim:
+ for (i = 0; i < IQK_NR; i++) {
+ j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */
+ if (bitmap & GENMASK(j + 1, j))
+ continue;
+
+ result[IQK_ROUND_HYBRID][i] = result[c1][i];
+ }
+
+ return false;
+}
+
+static
+void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
+{
+ if (path == PATH_S0) {
+ rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A);
+ rtw8723d_iqk_path_adda_on(rtwdev);
+ }
+
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+ rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+ rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+ if (path == PATH_S1) {
+ rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B);
+ rtw8723d_iqk_path_adda_on(rtwdev);
+ }
+}
+
+#define PATH_IQK_RETRY 2
+
+static
+void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
+ const struct iqk_backup_regs *backup)
+{
+ u32 i;
+ u8 s1_ok, s0_ok;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t);
+
+ rtw8723d_iqk_path_adda_on(rtwdev);
+ rtw8723d_iqk_config_mac(rtwdev);
+ rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf);
+ rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611);
+ rtw_write32(rtwdev, REG_TRMUX_11N, 0x000800e4);
+ rtw_write32(rtwdev, REG_BB_PWR_SAV1_11N, 0x25204200);
+ rtw8723d_iqk_precfg_path(rtwdev, PATH_S1);
+
+ for (i = 0; i < PATH_IQK_RETRY; i++) {
+ s1_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup);
+ if (s1_ok == IQK_TX_OK) {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] path S1 Tx IQK Success!!\n");
+ result[t][IQK_S1_TX_X] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+ result[t][IQK_S1_TX_Y] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Tx IQK Fail!!\n");
+ result[t][IQK_S1_TX_X] = 0x100;
+ result[t][IQK_S1_TX_Y] = 0x0;
+ }
+
+ for (i = 0; i < PATH_IQK_RETRY; i++) {
+ s1_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup);
+ if (s1_ok == (IQK_TX_OK | IQK_RX_OK)) {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] path S1 Rx IQK Success!!\n");
+ result[t][IQK_S1_RX_X] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+ result[t][IQK_S1_RX_Y] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Rx IQK Fail!!\n");
+ result[t][IQK_S1_RX_X] = 0x100;
+ result[t][IQK_S1_RX_Y] = 0x0;
+ }
+
+ if (s1_ok == 0x0)
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 IQK is failed!!\n");
+
+ rtw8723d_iqk_precfg_path(rtwdev, PATH_S0);
+
+ for (i = 0; i < PATH_IQK_RETRY; i++) {
+ s0_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup);
+ if (s0_ok == IQK_TX_OK) {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] path S0 Tx IQK Success!!\n");
+ result[t][IQK_S0_TX_X] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+ result[t][IQK_S0_TX_Y] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Tx IQK Fail!!\n");
+ result[t][IQK_S0_TX_X] = 0x100;
+ result[t][IQK_S0_TX_Y] = 0x0;
+ }
+
+ for (i = 0; i < PATH_IQK_RETRY; i++) {
+ s0_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup);
+ if (s0_ok == (IQK_TX_OK | IQK_RX_OK)) {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] path S0 Rx IQK Success!!\n");
+
+ result[t][IQK_S0_RX_X] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+ result[t][IQK_S0_RX_Y] =
+ rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Rx IQK Fail!!\n");
+ result[t][IQK_S0_RX_X] = 0x100;
+ result[t][IQK_S0_RX_Y] = 0x0;
+ }
+
+ if (s0_ok == 0x0)
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 IQK is failed!!\n");
+
+ rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+ mdelay(1);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] back to BB mode, load original value!\n");
+}
+
+static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ s32 result[IQK_ROUND_SIZE][IQK_NR];
+ struct iqk_backup_regs backup;
+ u8 i, j;
+ u8 final_candidate = IQK_ROUND_INVALID;
+ bool good;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n");
+
+ memset(result, 0, sizeof(result));
+
+ rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup);
+ rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup);
+ rtw8723d_iqk_backup_regs(rtwdev, &backup);
+
+ for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) {
+ rtw8723d_iqk_config_path_ctrl(rtwdev);
+ rtw8723d_iqk_config_lte_path_gnt(rtwdev);
+
+ rtw8723d_iqk_one_round(rtwdev, result, i, &backup);
+
+ if (i > IQK_ROUND_0)
+ rtw8723d_iqk_restore_regs(rtwdev, &backup);
+ rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup);
+ rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup);
+
+ for (j = IQK_ROUND_0; j < i; j++) {
+ good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i);
+
+ if (good) {
+ final_candidate = j;
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] cmp %d:%d final_candidate is %x\n",
+ j, i, final_candidate);
+ goto iqk_done;
+ }
+ }
+ }
+
+ if (final_candidate == IQK_ROUND_INVALID) {
+ s32 reg_tmp = 0;
+
+ for (i = 0; i < IQK_NR; i++)
+ reg_tmp += result[IQK_ROUND_HYBRID][i];
+
+ if (reg_tmp != 0) {
+ final_candidate = IQK_ROUND_HYBRID;
+ } else {
+ WARN(1, "IQK is failed\n");
+ goto out;
+ }
+ }
+
+iqk_done:
+ rtw8723d_iqk_fill_s1_matrix(rtwdev, result[final_candidate]);
+ rtw8723d_iqk_fill_s0_matrix(rtwdev, result[final_candidate]);
+
+ dm_info->iqk.result.s1_x = result[final_candidate][IQK_S1_TX_X];
+ dm_info->iqk.result.s1_y = result[final_candidate][IQK_S1_TX_Y];
+ dm_info->iqk.result.s0_x = result[final_candidate][IQK_S0_TX_X];
+ dm_info->iqk.result.s0_y = result[final_candidate][IQK_S0_TX_Y];
+ dm_info->iqk.done = true;
+
+out:
+ rtw_write32(rtwdev, REG_BB_SEL_BTG, backup.bb_sel_btg);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] final_candidate is %x\n",
+ final_candidate);
+
+ for (i = IQK_ROUND_0; i < IQK_ROUND_SIZE; i++)
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK] Result %u: rege94_s1=%x rege9c_s1=%x regea4_s1=%x regeac_s1=%x rege94_s0=%x rege9c_s0=%x regea4_s0=%x regeac_s0=%x %s\n",
+ i,
+ result[i][0], result[i][1], result[i][2], result[i][3],
+ result[i][4], result[i][5], result[i][6], result[i][7],
+ final_candidate == i ? "(final candidate)" : "");
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK]0xc80 = 0x%x 0xc94 = 0x%x 0xc14 = 0x%x 0xca0 = 0x%x\n",
+ rtw_read32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE),
+ rtw_read32(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N),
+ rtw_read32(rtwdev, REG_A_RXIQI),
+ rtw_read32(rtwdev, REG_RXIQK_MATRIX_LSB_11N));
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "[IQK]0xcd0 = 0x%x 0xcd4 = 0x%x 0xcd8 = 0x%x\n",
+ rtw_read32(rtwdev, REG_TXIQ_AB_S0),
+ rtw_read32(rtwdev, REG_TXIQ_CD_S0),
+ rtw_read32(rtwdev, REG_RXIQ_AB_S0));
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n");
+}
+
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
@@ -670,6 +1499,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
.cfg_ldo25 = rtw8723d_cfg_ldo25,
.efuse_grant = rtw8723d_efuse_grant,
.false_alarm_statistics = rtw8723d_false_alarm_statistics,
+ .phy_calibration = rtw8723d_phy_calibration,
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 64a1f2359c23..a31cf9d85f69 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -5,6 +5,34 @@
#ifndef __RTW8723D_H__
#define __RTW8723D_H__

+enum rtw8723d_path {
+ PATH_S1,
+ PATH_S0,
+ PATH_NR,
+};
+
+enum rtw8723d_iqk_round {
+ IQK_ROUND_0,
+ IQK_ROUND_1,
+ IQK_ROUND_2,
+ IQK_ROUND_HYBRID,
+ IQK_ROUND_SIZE,
+ IQK_ROUND_INVALID = 0xff,
+};
+
+enum rtw8723d_iqk_result {
+ IQK_S1_TX_X,
+ IQK_S1_TX_Y,
+ IQK_S1_RX_X,
+ IQK_S1_RX_Y,
+ IQK_S0_TX_X,
+ IQK_S0_TX_Y,
+ IQK_S0_RX_X,
+ IQK_S0_RX_Y,
+ IQK_NR,
+ IQK_SX_NR = IQK_NR / PATH_NR,
+};
+
struct rtw8723de_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
@@ -66,12 +94,35 @@ struct rtw8723d_efuse {
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))

+static inline s32 iqkxy_to_s32(s32 val)
+{
+ /* val is Q10.8 */
+ return sign_extend32(val, 9);
+}
+
+static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
+{
+ /* x, y and return value are Q10.8 */
+ s32 t;
+
+ t = x * y;
+ if (ext)
+ *ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
+
+ return (t >> 8); /* Q.16 --> Q.8 */
+}
+
+#define REG_BTG_SEL 0x0067
+#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_PSDFN 0x0808
+#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
+#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define REG_CCK0_SYS 0x0a00
+#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
@@ -86,11 +137,46 @@ struct rtw8723d_efuse {
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
+#define REG_BB_RX_PATH_11N 0x0c04
+#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
+#define REG_A_RXIQI 0x0c14
+#define BIT_MASK_RXIQ_S1_X 0x000003FF
+#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
+#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
+#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
+#define BIT_MASK_OFDM0_EXT_A BIT(31)
+#define BIT_MASK_OFDM0_EXT_C BIT(29)
+#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
+#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
+#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
+#define BIT_MASK_TXIQ_ELM_A 0x03ff
+#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
+ ((a) & 0x03ff))
+#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
+#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
+#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
+#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
+#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
+#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
+#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
+#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
+#define REG_TXIQ_AB_S0 0x0cd0
+#define BIT_MASK_TXIQ_A_S0 0x000007FE
+#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
+#define BIT_MASK_TXIQ_B_S0 0x0007E000
+#define REG_TXIQ_CD_S0 0x0cd4
+#define BIT_MASK_TXIQ_C_S0 0x000007FE
+#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
+#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
+#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
+#define REG_RXIQ_AB_S0 0x0cd8
+#define BIT_MASK_RXIQ_X_S0 0x000003FF
+#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
@@ -112,6 +198,32 @@ struct rtw8723d_efuse {
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
+#define REG_FPGA0_IQK_11N 0x0e28
+#define BIT_MASK_IQK_MOD 0xffffff00
+#define EN_IQK 0x808000
+#define RST_IQK 0x000000
+#define REG_TXIQK_TONE_A_11N 0x0e30
+#define REG_RXIQK_TONE_A_11N 0x0e34
+#define REG_TXIQK_PI_A_11N 0x0e38
+#define REG_RXIQK_PI_A_11N 0x0e3c
+#define REG_TXIQK_11N 0x0e40
+#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
+#define REG_RXIQK_11N 0x0e44
+#define REG_IQK_AGC_PTS_11N 0x0e48
+#define REG_IQK_AGC_RSP_11N 0x0e4c
+#define REG_TX_IQK_TONE_B 0x0e50
+#define REG_RX_IQK_TONE_B 0x0e54
+#define REG_IQK_RES_TX 0x0e94
+#define BIT_MASK_RES_TX GENMASK(25, 16)
+#define REG_IQK_RES_TY 0x0e9c
+#define BIT_MASK_RES_TY GENMASK(25, 16)
+#define REG_IQK_RES_RX 0x0ea4
+#define BIT_MASK_RES_RX GENMASK(25, 16)
+#define REG_IQK_RES_RY 0x0eac
+#define BIT_IQK_TX_FAIL BIT(28)
+#define BIT_IQK_RX_FAIL BIT(27)
+#define BIT_IQK_DONE BIT(26)
+#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
--
2.17.1

2020-04-17 07:50:34

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 36/40] rtw88: extract: make 8822c an individual kernel module

From: Zong-Zhe Yang <[email protected]>

Make objects about 8822c functions and 8822c tables,
i.e. rtw8822c.o and rtw8822c_table.o, an individual
kernel module called rtw88_8822c.ko.

For 8822c pcie chip, i.e. 8822CE chip, add a chip
entry point module called rtw88_8822ce.ko which
will depend on rtw88_8822c.ko and rtwpci.ko.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/Kconfig | 6 +++-
drivers/net/wireless/realtek/rtw88/Makefile | 7 ++++-
drivers/net/wireless/realtek/rtw88/main.h | 1 -
drivers/net/wireless/realtek/rtw88/pci.c | 3 --
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 5 ++++
.../net/wireless/realtek/rtw88/rtw8822ce.c | 30 +++++++++++++++++++
.../net/wireless/realtek/rtw88/rtw8822ce.h | 20 +++++++++++++
7 files changed, 66 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822ce.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822ce.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 7a5fa68945c4..f4dbb5914bde 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -16,6 +16,9 @@ config RTW88_CORE
config RTW88_PCI
tristate

+config RTW88_8822C
+ tristate
+
config RTW88_8822BE
bool "Realtek 8822BE PCI wireless network adapter"
depends on PCI
@@ -27,10 +30,11 @@ config RTW88_8822BE
802.11ac PCIe wireless network adapter

config RTW88_8822CE
- bool "Realtek 8822CE PCI wireless network adapter"
+ tristate "Realtek 8822CE PCI wireless network adapter"
depends on PCI
select RTW88_CORE
select RTW88_PCI
+ select RTW88_8822C
help
Select this option will enable support for 8822CE chipset

diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 385facc0dd20..e45efd2deaa3 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -19,8 +19,13 @@ rtw88-y += main.o \
regd.o

rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o
-rtw88-$(CONFIG_RTW88_8822CE) += rtw8822c.o rtw8822c_table.o
rtw88-$(CONFIG_RTW88_8723DE) += rtw8723d.o rtw8723d_table.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_PCI) += rtwpci.o
rtwpci-objs := pci.o
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 35e2fb19ad56..d5514a33b109 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -40,7 +40,6 @@ extern unsigned int rtw_fw_lps_deep_mode;
extern unsigned int rtw_debug_mask;
extern const struct ieee80211_ops rtw_ops;
extern struct rtw_chip_info rtw8822b_hw_spec;
-extern struct rtw_chip_info rtw8822c_hw_spec;
extern struct rtw_chip_info rtw8723d_hw_spec;

#define RTW_MAX_CHANNEL_NUM_2G 14
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 66feaab0261e..90a6624065c1 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1601,9 +1601,6 @@ static const struct pci_device_id rtw_pci_id_table[] = {
#ifdef CONFIG_RTW88_8822BE
{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtw8822b_hw_spec) },
#endif
-#ifdef CONFIG_RTW88_8822CE
- { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822, rtw8822c_hw_spec) },
-#endif
#ifdef CONFIG_RTW88_8723DE
{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723, rtw8723d_hw_spec) },
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index d2e74ac21d07..5e9a77d94ca1 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2018-2019 Realtek Corporation
*/

+#include <linux/module.h>
#include "main.h"
#include "coex.h"
#include "fw.h"
@@ -4262,3 +4263,7 @@ EXPORT_SYMBOL(rtw8822c_hw_spec);

MODULE_FIRMWARE("rtw88/rtw8822c_fw.bin");
MODULE_FIRMWARE("rtw88/rtw8822c_wow_fw.bin");
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822c driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c
new file mode 100644
index 000000000000..c7d75edcaa2e
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "rtw8822ce.h"
+
+static const struct pci_device_id rtw_8822ce_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822),
+ .driver_data = (kernel_ulong_t)&rtw8822c_hw_spec
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(pci, rtw_8822ce_id_table);
+
+static struct pci_driver rtw_8822ce_driver = {
+ .name = "rtw_8822ce",
+ .id_table = rtw_8822ce_id_table,
+ .probe = rtw_pci_probe,
+ .remove = rtw_pci_remove,
+ .driver.pm = RTW_PM_OPS,
+ .shutdown = rtw_pci_shutdown,
+};
+module_pci_driver(rtw_8822ce_driver);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822ce driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h b/drivers/net/wireless/realtek/rtw88/rtw8822ce.h
new file mode 100644
index 000000000000..ed2eff4d5fd0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_8822CE_H_
+#define __RTW_8822CE_H_
+
+#ifdef CONFIG_PM
+extern const struct dev_pm_ops rtw_pci_pm;
+#define RTW_PM_OPS (&rtw_pci_pm)
+#else
+#define RTW_PM_OPS NULL
+#endif
+
+extern struct rtw_chip_info rtw8822c_hw_spec;
+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);
+
+#endif
--
2.17.1

2020-04-17 07:50:39

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 23/40] rtw88: 8723d: Set IG register for CCK rate

From: Ping-Ke Shih <[email protected]>

DIG sets only one IG register for most chips, but 8723D need to set
additional register for CCK rate.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/main.h | 1 +
drivers/net/wireless/realtek/rtw88/phy.c | 4 ++++
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 5 +++++
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 +
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 +
5 files changed, 12 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 157aca641f6d..d51eeda3627c 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1099,6 +1099,7 @@ struct rtw_chip_info {
const struct rtw_intf_phy_para_table *intf_table;

const struct rtw_hw_reg *dig;
+ const struct rtw_hw_reg *dig_cck;
u32 rf_base_addr[2];
u32 rf_sipi_addr[2];
const struct rtw_rf_sipi_addr *rf_sipi_read_addr;
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index 8489abfdc12e..72a16eff9db3 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -140,9 +140,13 @@ void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_hal *hal = &rtwdev->hal;
+ const struct rtw_hw_reg *dig_cck = &chip->dig_cck[0];
u32 addr, mask;
u8 path;

+ if (dig_cck)
+ rtw_write32_mask(rtwdev, dig_cck->addr, dig_cck->mask, igi >> 1);
+
for (path = 0; path < hal->rf_path_num; path++) {
addr = chip->dig[path].addr;
mask = chip->dig[path].mask;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index df78d3b4b07a..dd8943426bb3 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -1077,6 +1077,10 @@ static const struct rtw_hw_reg rtw8723d_dig[] = {
[1] = { .addr = 0xc50, .mask = 0x7f },
};

+static const struct rtw_hw_reg rtw8723d_dig_cck[] = {
+ [0] = { .addr = 0xa0c, .mask = 0x3f00 },
+};
+
static const struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = {
[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,
.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
@@ -1119,6 +1123,7 @@ struct rtw_chip_info rtw8723d_hw_spec = {
.page_table = page_table_8723d,
.rqpn_table = rqpn_table_8723d,
.dig = rtw8723d_dig,
+ .dig_cck = rtw8723d_dig_cck,
.rf_sipi_addr = {0x840, 0x844},
.rf_sipi_read_addr = rtw8723d_rf_sipi_addr,
.fix_rf_phy_num = 2,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index ffee8111d145..51b16a831162 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -2435,6 +2435,7 @@ struct rtw_chip_info rtw8822b_hw_spec = {
.rqpn_table = rqpn_table_8822b,
.intf_table = &phy_para_table_8822b,
.dig = rtw8822b_dig,
+ .dig_cck = NULL,
.rf_base_addr = {0x2800, 0x2c00},
.rf_sipi_addr = {0xc90, 0xe90},
.mac_tbl = &rtw8822b_mac_tbl,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 2c4ead6b3bef..b17b7cfbbe40 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -4183,6 +4183,7 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.rqpn_table = rqpn_table_8822c,
.intf_table = &phy_para_table_8822c,
.dig = rtw8822c_dig,
+ .dig_cck = NULL,
.rf_base_addr = {0x3c00, 0x4c00},
.rf_sipi_addr = {0x1808, 0x4108},
.mac_tbl = &rtw8822c_mac_tbl,
--
2.17.1

2020-04-17 07:50:41

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 25/40] rtw88: 8723d: Add LC calibration

From: Ping-Ke Shih <[email protected]>

LC calibration is done by hardware circuit. Driver sets the LCK bit to kick
start, and then poll the bit to check if it's done.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 30 +++++++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 2 ++
2 files changed, 32 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index cf897af380c1..94784c7f0743 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -64,6 +64,33 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = {
#define WLAN_LTR_CTRL1 0xCB004010
#define WLAN_LTR_CTRL2 0x01233425

+static void rtw8723d_lck(struct rtw_dev *rtwdev)
+{
+#define BIT_LCK BIT(15)
+ u8 val_ctx;
+ u32 lc_cal, cnt;
+
+ val_ctx = rtw_read8(rtwdev, REG_CTX);
+ if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
+ rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
+ else
+ rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
+ lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
+ for (cnt = 0; cnt < 100; cnt++) {
+ if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK) != 0x1)
+ break;
+ mdelay(10);
+ }
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
+ if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
+ rtw_write8(rtwdev, REG_CTX, val_ctx);
+ else
+ rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
+}
+
static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
{
u8 xtal_cap;
@@ -125,6 +152,9 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw_phy_init(rtwdev);

rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
+
+ rtw8723d_lck(rtwdev);
+
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20);
}
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index b5b7fc9cd1c8..64a1f2359c23 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -97,6 +97,8 @@ struct rtw8723d_efuse {
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
+#define REG_CTX 0x0d03
+#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
--
2.17.1

2020-04-17 07:50:45

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 20/40] rtw88: handle C2H_CCX_TX_RPT to know if packet TX'ed successfully

From: Ping-Ke Shih <[email protected]>

TX status report of 8723D differs from 8822B/8822C, it uses
C2H_CCX_TX_RPT (0x03) with different format. With sequence number
and TX status, driver can know if certain packet was transmitted
successfully.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/fw.c | 6 +++++-
drivers/net/wireless/realtek/rtw88/fw.h | 7 +++++--
drivers/net/wireless/realtek/rtw88/tx.c | 11 ++++++++---
drivers/net/wireless/realtek/rtw88/tx.h | 2 +-
4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index dde7823143ea..11fa1fc7f1cb 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -25,7 +25,7 @@ static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,

switch (sub_cmd_id) {
case C2H_CCX_RPT:
- rtw_tx_report_handle(rtwdev, skb);
+ rtw_tx_report_handle(rtwdev, skb, C2H_CCX_RPT);
break;
default:
break;
@@ -142,6 +142,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
goto unlock;

switch (c2h->id) {
+ case C2H_CCX_TX_RPT:
+ rtw_tx_report_handle(rtwdev, skb, C2H_CCX_TX_RPT);
+ break;
case C2H_BT_INFO:
rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
break;
@@ -155,6 +158,7 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
rtw_fw_ra_report_handle(rtwdev, c2h->payload, len);
break;
default:
+ rtw_dbg(rtwdev, RTW_DBG_FW, "C2H 0x%x isn't handled\n", c2h->id);
break;
}

diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 2933ef741e53..470e1809645a 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -26,6 +26,7 @@
#define FW_START_ADDR_LEGACY 0x1000

enum rtw_c2h_cmd_id {
+ C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09,
C2H_BT_MP_INFO = 0x0b,
C2H_RA_RPT = 0x0c,
@@ -218,8 +219,10 @@ struct rtw_fw_hdr_legacy {
} __packed;

/* C2H */
-#define GET_CCX_REPORT_SEQNUM(c2h_payload) (c2h_payload[8] & 0xfc)
-#define GET_CCX_REPORT_STATUS(c2h_payload) (c2h_payload[9] & 0xc0)
+#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_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f)
#define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7)
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 60989987f67b..79c42118825f 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -196,7 +196,7 @@ static void rtw_tx_report_tx_status(struct rtw_dev *rtwdev,
ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
}

-void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
+void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
struct rtw_c2h_cmd *c2h;
@@ -207,8 +207,13 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)

c2h = get_c2h_from_skb(skb);

- sn = GET_CCX_REPORT_SEQNUM(c2h->payload);
- st = GET_CCX_REPORT_STATUS(c2h->payload);
+ if (src == C2H_CCX_TX_RPT) {
+ sn = GET_CCX_REPORT_SEQNUM_V0(c2h->payload);
+ st = GET_CCX_REPORT_STATUS_V0(c2h->payload);
+ } else {
+ sn = GET_CCX_REPORT_SEQNUM_V1(c2h->payload);
+ st = GET_CCX_REPORT_STATUS_V1(c2h->payload);
+ }

spin_lock_irqsave(&tx_report->q_lock, flags);
skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index b973de0f4dc0..72dfd4059f03 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -95,7 +95,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct sk_buff *skb);
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
-void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
+void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb);
--
2.17.1

2020-04-17 07:51:08

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 10/40] rtw88: no need to send additional information to legacy firmware

From: Ping-Ke Shih <[email protected]>

The firmware of 11AC devices need more information to support more offload
functions, such as IQK. And 11N devices such as 8723D does not support
offload these function in firmware, there is no need to send these additional
information to firmware when it comes to 11N devices.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/fw.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 209853fdcb42..dde7823143ea 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -271,6 +271,9 @@ rtw_fw_send_general_info(struct rtw_dev *rtwdev)
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
u16 total_size = H2C_PKT_HDR_SIZE + 4;

+ if (rtw_chip_wcpu_11n(rtwdev))
+ return;
+
rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO);

SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
@@ -291,6 +294,9 @@ rtw_fw_send_phydm_info(struct rtw_dev *rtwdev)
u16 total_size = H2C_PKT_HDR_SIZE + 8;
u8 fw_rf_type = 0;

+ if (rtw_chip_wcpu_11n(rtwdev))
+ return;
+
if (hal->rf_type == RF_1T1R)
fw_rf_type = FW_RF_1T1R;
else if (hal->rf_type == RF_2T2R)
--
2.17.1

2020-04-17 08:20:34

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

<[email protected]> writes:

> From: Yan-Hsuan Chuang <[email protected]>
>
> Although RTL8723DE devices are 802.11n devices, while rtw88
> aimed to support for 802.11ac devices, the 8723DE devices's
> architecture is relatively close to the 802.11ac devices.
> So, add support for them on rtw88, with some minor modifications.

There's no way I'm going to review 40 patches in one go :) So I'll just
to look at around 10 first patches and drop the rest.

If you want your patches reviewed smoothly submit only around 7-12
patches per patchset. If the patches are bigger don't send more than 7
patches. But if they smaller, or trivial patches, 12 patches is ok. But
anything more than 12 patches and I'm sure you will get reviewers
grumpy.

But you can submit multiple patchsets, just try to throttle it down to
avoid bufferbloat in patchwork, ie. send a new patchset every other day
and document the dependencies in the cover letter ("this patchset
depends on patchset B").

--
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2020-04-17 08:27:24

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

Kalle Valo <[email protected]> writes:

> <[email protected]> writes:
>
>> From: Yan-Hsuan Chuang <[email protected]>
>>
>> Although RTL8723DE devices are 802.11n devices, while rtw88
>> aimed to support for 802.11ac devices, the 8723DE devices's
>> architecture is relatively close to the 802.11ac devices.
>> So, add support for them on rtw88, with some minor modifications.
>
> There's no way I'm going to review 40 patches in one go :) So I'll just
> to look at around 10 first patches and drop the rest.
>
> If you want your patches reviewed smoothly submit only around 7-12
> patches per patchset. If the patches are bigger don't send more than 7
> patches. But if they smaller, or trivial patches, 12 patches is ok. But
> anything more than 12 patches and I'm sure you will get reviewers
> grumpy.
>
> But you can submit multiple patchsets, just try to throttle it down to
> avoid bufferbloat in patchwork, ie. send a new patchset every other day
> and document the dependencies in the cover letter ("this patchset
> depends on patchset B").

I added this also to the wiki:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#maximum_of_7-12_patches_per_patchset

--
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2020-04-17 09:06:58

by Tony Chuang

[permalink] [raw]
Subject: RE: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

Kalle Valo <[email protected]> writes:
>
> > <[email protected]> writes:
> >
> >> From: Yan-Hsuan Chuang <[email protected]>
> >>
> >> Although RTL8723DE devices are 802.11n devices, while rtw88
> >> aimed to support for 802.11ac devices, the 8723DE devices's
> >> architecture is relatively close to the 802.11ac devices.
> >> So, add support for them on rtw88, with some minor modifications.
> >
> > There's no way I'm going to review 40 patches in one go :) So I'll just
> > to look at around 10 first patches and drop the rest.
> >
> > If you want your patches reviewed smoothly submit only around 7-12
> > patches per patchset. If the patches are bigger don't send more than 7
> > patches. But if they smaller, or trivial patches, 12 patches is ok. But
> > anything more than 12 patches and I'm sure you will get reviewers
> > grumpy.
> >
> > But you can submit multiple patchsets, just try to throttle it down to
> > avoid bufferbloat in patchwork, ie. send a new patchset every other day
> > and document the dependencies in the cover letter ("this patchset
> > depends on patchset B").
>
> I added this also to the wiki:
>
> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpa
> tches#maximum_of_7-12_patches_per_patchset
>

Actually I can send the 8723DE within 5 patches, but I thought that split
them will be easier to review :) If too many patches is a problem, then I
can squash them back together, because most of them are hardware
settings. I can resend a v2.

Yen-Hsuan

2020-04-17 14:56:38

by Stefan Schmidt

[permalink] [raw]
Subject: Re: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

Hello Yen-Hsuan

On 17.04.20 11:03, Tony Chuang wrote:
> Kalle Valo <[email protected]> writes:
>>
>>> <[email protected]> writes:
>>>
>>>> From: Yan-Hsuan Chuang <[email protected]>
>>>>
>>>> Although RTL8723DE devices are 802.11n devices, while rtw88
>>>> aimed to support for 802.11ac devices, the 8723DE devices's
>>>> architecture is relatively close to the 802.11ac devices.
>>>> So, add support for them on rtw88, with some minor modifications.
>>>
>>> There's no way I'm going to review 40 patches in one go :) So I'll just
>>> to look at around 10 first patches and drop the rest.
>>>
>>> If you want your patches reviewed smoothly submit only around 7-12
>>> patches per patchset. If the patches are bigger don't send more than 7
>>> patches. But if they smaller, or trivial patches, 12 patches is ok. But
>>> anything more than 12 patches and I'm sure you will get reviewers
>>> grumpy.
>>>
>>> But you can submit multiple patchsets, just try to throttle it down to
>>> avoid bufferbloat in patchwork, ie. send a new patchset every other day
>>> and document the dependencies in the cover letter ("this patchset
>>> depends on patchset B").
>>
>> I added this also to the wiki:
>>
>> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpa
>> tches#maximum_of_7-12_patches_per_patchset
>>
>
> Actually I can send the 8723DE within 5 patches, but I thought that split
> them will be easier to review :) If too many patches is a problem, then I
> can squash them back together, because most of them are hardware
> settings. I can resend a v2.

Squashing them together to stay below the patch limit would not really
help reviewers. Its the same amount of code, just in bigger patches.

Most reviewers are way more happy with smaller patches doing one thing
only (atomic). I would assume that Kalle would prefer to keep the
patches split up as you already did. Just arrange them in a few sets
coming in after another. Its really about throttling the amount of code
coming in that needs review to be manageable for reviewers.

regards
Stefan Schmidt

2020-04-21 08:26:28

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/40] rtw88: add support for 802.11n RTL8723DE devices

Stefan Schmidt <[email protected]> writes:

> Hello Yen-Hsuan
>
> On 17.04.20 11:03, Tony Chuang wrote:
>> Kalle Valo <[email protected]> writes:
>>>
>>>> <[email protected]> writes:
>>>>
>>>>> From: Yan-Hsuan Chuang <[email protected]>
>>>>>
>>>>> Although RTL8723DE devices are 802.11n devices, while rtw88
>>>>> aimed to support for 802.11ac devices, the 8723DE devices's
>>>>> architecture is relatively close to the 802.11ac devices.
>>>>> So, add support for them on rtw88, with some minor modifications.
>>>>
>>>> There's no way I'm going to review 40 patches in one go :) So I'll just
>>>> to look at around 10 first patches and drop the rest.
>>>>
>>>> If you want your patches reviewed smoothly submit only around 7-12
>>>> patches per patchset. If the patches are bigger don't send more than 7
>>>> patches. But if they smaller, or trivial patches, 12 patches is ok. But
>>>> anything more than 12 patches and I'm sure you will get reviewers
>>>> grumpy.
>>>>
>>>> But you can submit multiple patchsets, just try to throttle it down to
>>>> avoid bufferbloat in patchwork, ie. send a new patchset every other day
>>>> and document the dependencies in the cover letter ("this patchset
>>>> depends on patchset B").
>>>
>>> I added this also to the wiki:
>>>
>>> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpa
>>> tches#maximum_of_7-12_patches_per_patchset
>>>
>>
>> Actually I can send the 8723DE within 5 patches, but I thought that split
>> them will be easier to review :) If too many patches is a problem, then I
>> can squash them back together, because most of them are hardware
>> settings. I can resend a v2.
>
> Squashing them together to stay below the patch limit would not really
> help reviewers. Its the same amount of code, just in bigger patches.
>
> Most reviewers are way more happy with smaller patches doing one thing
> only (atomic). I would assume that Kalle would prefer to keep the
> patches split up as you already did. Just arrange them in a few sets
> coming in after another. Its really about throttling the amount of
> code coming in that needs review to be manageable for reviewers.

Exactly, thanks Stefan for explaining it so clearly.

--
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

Subject: Re: [PATCH 25/40] rtw88: 8723d: Add LC calibration

On 2020-04-17 15:46:38 [+0800], [email protected] wrote:
> index cf897af380c1..94784c7f0743 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> @@ -64,6 +64,33 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = {
> #define WLAN_LTR_CTRL1 0xCB004010
> #define WLAN_LTR_CTRL2 0x01233425
>
> +static void rtw8723d_lck(struct rtw_dev *rtwdev)
> +{
> +#define BIT_LCK BIT(15)

please don't add defines like this within a function.

> + u8 val_ctx;
> + u32 lc_cal, cnt;
> +
> + val_ctx = rtw_read8(rtwdev, REG_CTX);
> + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
> + rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
> + else
> + rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
> + lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
> +
> + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
> + for (cnt = 0; cnt < 100; cnt++) {
> + if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK) != 0x1)
> + break;
> + mdelay(10);

Do you have any numbers on how long this takes? Like best-case, on average,
worst case? I'm asking because if the bit does not flip on the first
read then you busy-loop-delay here for 10ms. If it does not flip at all,
you busy waited a whole second without any consequence.

It looks like this context here is not atomic so msleep() would work where.

Sebastian

Subject: Re: [PATCH 26/40] rtw88: 8723d: add IQ calibration

On 2020-04-17 15:46:39 [+0800], [email protected] wrote:
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> index 94784c7f0743..b66bd969e007 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c

> +struct iqk_backup_regs {
> + u32 adda[IQK_ADDA_REG_NUM];
> + u8 mac8[IQK_MAC8_REG_NUM];
> + u32 mac32[IQK_MAC32_REG_NUM];
> + u32 bb[IQK_BB_REG_NUM];
> +
> + u32 lte_path;
> + u32 lte_gnt;
> +
> + u8 btg_sel;
> + u32 bb_sel_btg;
> +
> + u8 igia;
> + u8 igib;

The struct has 128 bytes. Putting btg_sel after bb_sel_btg will result
in 124 bytes. How likely is it that it will grow? I'm asking because it
is allocated on stack.

> +};
> +
> +static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
> + struct iqk_backup_regs *backup)
> +{
> + int i;
> +
> + for (i = 0; i < IQK_ADDA_REG_NUM; i++)
> + backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
> +
> + for (i = 0; i < IQK_MAC8_REG_NUM; i++)
> + backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
> + for (i = 0; i < IQK_MAC32_REG_NUM; i++)
> + backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
> +
> + for (i = 0; i < IQK_BB_REG_NUM; i++)
> + backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
> +
> + backup->igia = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
> + backup->igib = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);

igi[ab] is alreay u8, no need for cast.

> +
> + backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
> +}


> +static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
> + const struct rtw_8723d_iqk_cfg *iqk_cfg,
> + const struct iqk_backup_regs *backup)
> +{
> + u32 tx_x, tx_y;
> + u8 result = 0x00;

You could avoid the explicit init of `result' (maybe even use `ret' for
less key strokes and avoiding the confusion with the `result' array used
by the other functions here) and then


> + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
> + result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);

not or the returned value here. Since you don't collect it from multiple
functions I don't see the reason for it.

> + if (!result)
> + goto restore;

> + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
> + result |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg);

Same here.

> +restore:
> + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
> +
> + return result;
> +}
> +

> +
> +static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
> +{
> + struct rtw_dm_info *dm_info = &rtwdev->dm_info;
> + s32 result[IQK_ROUND_SIZE][IQK_NR];
> + struct iqk_backup_regs backup;

I don't know how deep you are in the call chain, but `result' takes 128
bytes and `backup' as well (this could be 124).
I'm not saying that this is bad, just that you keep an eye on it since
those two take 256 bytes.

> + u8 i, j;
> + u8 final_candidate = IQK_ROUND_INVALID;
> + bool good;
> +
> + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n");
> +
> + memset(result, 0, sizeof(result));

Sebastian

2020-05-04 08:59:15

by Tony Chuang

[permalink] [raw]
Subject: RE: [PATCH 25/40] rtw88: 8723d: Add LC calibration

> On 2020-04-17 15:46:38 [+0800], [email protected] wrote:
> > index cf897af380c1..94784c7f0743 100644
> > --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > @@ -64,6 +64,33 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = {
> > #define WLAN_LTR_CTRL1 0xCB004010
> > #define WLAN_LTR_CTRL2 0x01233425
> >
> > +static void rtw8723d_lck(struct rtw_dev *rtwdev)
> > +{
> > +#define BIT_LCK BIT(15)
>
> please don't add defines like this within a function.
>
> > + u8 val_ctx;
> > + u32 lc_cal, cnt;
> > +
> > + val_ctx = rtw_read8(rtwdev, REG_CTX);
> > + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
> > + rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
> > + else
> > + rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
> > + lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
> > +
> > + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal |
> BIT_LCK);
> > + for (cnt = 0; cnt < 100; cnt++) {
> > + if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK) != 0x1)
> > + break;
> > + mdelay(10);
>
> Do you have any numbers on how long this takes? Like best-case, on average,
> worst case? I'm asking because if the bit does not flip on the first
> read then you busy-loop-delay here for 10ms. If it does not flip at all,
> you busy waited a whole second without any consequence.
>
> It looks like this context here is not atomic so msleep() would work where.

Indeed, I think read_poll_timeout() will be good for this case. Thanks.

>
> Sebastian
>

Yen-Hsuan

2020-05-04 09:47:31

by Tony Chuang

[permalink] [raw]
Subject: RE: [PATCH 26/40] rtw88: 8723d: add IQ calibration

Sebastian Andrzej Siewior <[email protected]> writes:

> On 2020-04-17 15:46:39 [+0800], [email protected] wrote:
> > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > index 94784c7f0743..b66bd969e007 100644
> > --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> …
> > +struct iqk_backup_regs {
> > + u32 adda[IQK_ADDA_REG_NUM];
> > + u8 mac8[IQK_MAC8_REG_NUM];
> > + u32 mac32[IQK_MAC32_REG_NUM];
> > + u32 bb[IQK_BB_REG_NUM];
> > +
> > + u32 lte_path;
> > + u32 lte_gnt;
> > +
> > + u8 btg_sel;
> > + u32 bb_sel_btg;
> > +
> > + u8 igia;
> > + u8 igib;
>
> The struct has 128 bytes. Putting btg_sel after bb_sel_btg will result
> in 124 bytes. How likely is it that it will grow? I'm asking because it
> is allocated on stack.

We need to backup a lot of the register values for doing IQK.
I think it's inevitable, just about where should we put them.
And as there's only 8723D is using SW IQK, this struct will only be
used by 8723D, so add them into rtwdev is not suitable.

Another way is that we can kmalloc() and then kfree() it after
IQK is done.

>
> > +};
> > +
> > +static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
> > + struct iqk_backup_regs *backup)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < IQK_ADDA_REG_NUM; i++)
> > + backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
> > +
> > + for (i = 0; i < IQK_MAC8_REG_NUM; i++)
> > + backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
> > + for (i = 0; i < IQK_MAC32_REG_NUM; i++)
> > + backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
> > +
> > + for (i = 0; i < IQK_BB_REG_NUM; i++)
> > + backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
> > +
> > + backup->igia = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1,
> MASKBYTE0);
> > + backup->igib = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1,
> MASKBYTE0);
>
> igi[ab] is alreay u8, no need for cast.

It's because rtw_read32_mask() returns u32, but because we
mask with one byte only.

>
> > +
> > + backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
> > +}
> …
>
> > +static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
> > + const struct rtw_8723d_iqk_cfg *iqk_cfg,
> > + const struct iqk_backup_regs *backup)
> > +{
> > + u32 tx_x, tx_y;
> > + u8 result = 0x00;
>
> You could avoid the explicit init of `result' (maybe even use `ret' for
> less key strokes and avoiding the confusion with the `result' array used
> by the other functions here) and then

The result should be inited to zero here, because the value
of it is or-ed by the IQK status, such as:

result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);

And yes, the name is a little confused to be the same.
Should use different name for them.

>
> …
> > + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
> > + result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
>
> not or the returned value here. Since you don't collect it from multiple
> functions I don't see the reason for it.

It actually does collect them from two functions, they are the
same, but are done twice, hence using |= here.

>
> > + if (!result)
> > + goto restore;
> …
> > + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
> > + result |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg);
>
> Same here.
>
> > +restore:
> > + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
> > +
> > + return result;
> > +}
> > +
> …
> > +
> > +static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
> > +{
> > + struct rtw_dm_info *dm_info = &rtwdev->dm_info;
> > + s32 result[IQK_ROUND_SIZE][IQK_NR];
> > + struct iqk_backup_regs backup;
>
> I don't know how deep you are in the call chain, but `result' takes 128
> bytes and `backup' as well (this could be 124).
> I'm not saying that this is bad, just that you keep an eye on it since
> those two take 256 bytes.

I can try to fix it, to see if we can reduce that.

>
> > + u8 i, j;
> > + u8 final_candidate = IQK_ROUND_INVALID;
> > + bool good;
> > +
> > + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n");
> > +
> > + memset(result, 0, sizeof(result));
>
> Sebastian
>

Yen-Hsuan

Subject: Re: [PATCH 26/40] rtw88: 8723d: add IQ calibration

On 2020-05-04 09:45:48 [+0000], Tony Chuang wrote:
> Sebastian Andrzej Siewior <[email protected]> writes:
>
> > On 2020-04-17 15:46:39 [+0800], [email protected] wrote:
> > > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > > index 94784c7f0743..b66bd969e007 100644
> > > --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > > +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
> > …
> > > +struct iqk_backup_regs {
> > > + u32 adda[IQK_ADDA_REG_NUM];
> > > + u8 mac8[IQK_MAC8_REG_NUM];
> > > + u32 mac32[IQK_MAC32_REG_NUM];
> > > + u32 bb[IQK_BB_REG_NUM];
> > > +
> > > + u32 lte_path;
> > > + u32 lte_gnt;
> > > +
> > > + u8 btg_sel;
> > > + u32 bb_sel_btg;
> > > +
> > > + u8 igia;
> > > + u8 igib;
> >
> > The struct has 128 bytes. Putting btg_sel after bb_sel_btg will result
> > in 124 bytes. How likely is it that it will grow? I'm asking because it
> > is allocated on stack.
>
> We need to backup a lot of the register values for doing IQK.
> I think it's inevitable, just about where should we put them.
> And as there's only 8723D is using SW IQK, this struct will only be
> used by 8723D, so add them into rtwdev is not suitable.
>
> Another way is that we can kmalloc() and then kfree() it after
> IQK is done.

I'm not saying that it is a problem now, just pointing out that in the
end you store ~256 bytes on the stack. So if it remains in that size, it
should be okay but if it grows further then it might become problematic.
In the end you have 8KiB of stack and as I said, I have no idea how deep
you are right now.

> > > +};
> > > +
> > > +static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
> > > + struct iqk_backup_regs *backup)
> > > +{
> > > + int i;
> > > +
> > > + for (i = 0; i < IQK_ADDA_REG_NUM; i++)
> > > + backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
> > > +
> > > + for (i = 0; i < IQK_MAC8_REG_NUM; i++)
> > > + backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
> > > + for (i = 0; i < IQK_MAC32_REG_NUM; i++)
> > > + backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
> > > +
> > > + for (i = 0; i < IQK_BB_REG_NUM; i++)
> > > + backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
> > > +
> > > + backup->igia = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1,
> > MASKBYTE0);
> > > + backup->igib = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1,
> > MASKBYTE0);
> >
> > igi[ab] is alreay u8, no need for cast.
>
> It's because rtw_read32_mask() returns u32, but because we
> mask with one byte only.

Right. However I don't think that it makes any difference in this case.

> >
> > > +
> > > + backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
> > > +}
> > …
> >
> > > +static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
> > > + const struct rtw_8723d_iqk_cfg *iqk_cfg,
> > > + const struct iqk_backup_regs *backup)
> > > +{
> > > + u32 tx_x, tx_y;
> > > + u8 result = 0x00;
> >
> > You could avoid the explicit init of `result' (maybe even use `ret' for
> > less key strokes and avoiding the confusion with the `result' array used
> > by the other functions here) and then
>
> The result should be inited to zero here, because the value
> of it is or-ed by the IQK status, such as:
>
> result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
>
> And yes, the name is a little confused to be the same.
> Should use different name for them.
>
> >
> > …
> > > + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
> > > + result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
> >
> > not or the returned value here. Since you don't collect it from multiple
> > functions I don't see the reason for it.
>
> It actually does collect them from two functions, they are the
> same, but are done twice, hence using |= here.

Oh indeed it is. I was expecting a code flow with continue on 0 and
abort otherwise and that BIT(0) confused me.
So the first one could become a real assignment, the second has to be
ORed to keep current code flow.

Sebastian