summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw88/hci.h
diff options
context:
space:
mode:
authorYan-Hsuan Chuang <yhchuang@realtek.com>2019-04-26 15:17:37 +0300
committerKalle Valo <kvalo@codeaurora.org>2019-04-30 19:43:37 +0300
commite3037485c68ec1a299ff41160d8fedbd4abc29b9 (patch)
treefaa639e769935576679cf6d3495d133f697c2076 /drivers/net/wireless/realtek/rtw88/hci.h
parentc745f72266603b13de57d24b3b559fbeea275bf2 (diff)
rtw88: new Realtek 802.11ac driver
This is a new mac80211 driver for Realtek 802.11ac wireless network chips. rtw88 now supports RTL8822BE/RTL8822CE now, with basic station mode functionalities. The firmware for both can be found at linux-firmware. https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git For RTL8822BE: rtw88/rtw8822b_fw.bin For RTL8822CE: rtw88/rtw8822c_fw.bin And for now, only PCI buses (RTL8xxxE) are supported. We will add support for USB and SDIO in the future. The bus interface abstraction can be seen in this driver such as hci.h. Most of the hardware setting are the same except for some TRX path or probing setup should be separated. Supported: * Basic STA/AP/ADHOC mode, and TDLS (STA is well tested) Missing feature: * WOW/PNO * USB & SDIO bus (such as RTL8xxxU/RTL8xxxS) * BT coexistence (8822B/8822C are combo ICs) * Multiple interfaces (for now single STA is better supported) * Dynamic hardware calibrations (to improve/stabilize performance) Potential problems: * static calibration spends too much time, and it is painful for driver to leave IDLE state. And slows down associate process. But reload function are under development, will be added soon! * TRX statictics misleading, as we are not reporting status correctly, or say, not reporting for "every" packet. The next patch set should have BT coexistence code since RTL8822B/C are combo ICs, and the driver for BT can be found after Linux Kernel v4.20. So it is better to add it first to make WiFi + BT work concurrently. Although now rtw88 is simple but we are developing more features for it. Even we want to add support for more chips such as RTL8821C/RTL8814B. Finally, rtw88 has many authors, listed alphabetically: Ping-Ke Shih <pkshih@realtek.com> Tzu-En Huang <tehuang@realtek.com> Yan-Hsuan Chuang <yhchuang@realtek.com> Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com> Reviewed-by: Brian Norris <briannorris@chromium.org> Tested-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/hci.h')
-rw-r--r--drivers/net/wireless/realtek/rtw88/hci.h211
1 files changed, 211 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h
new file mode 100644
index 000000000000..2676582a85a0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/hci.h
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_HCI_H__
+#define __RTW_HCI_H__
+
+/* ops for PCI, USB and SDIO */
+struct rtw_hci_ops {
+ int (*tx)(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb);
+ int (*setup)(struct rtw_dev *rtwdev);
+ int (*start)(struct rtw_dev *rtwdev);
+ void (*stop)(struct rtw_dev *rtwdev);
+
+ int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
+ int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
+
+ u8 (*read8)(struct rtw_dev *rtwdev, u32 addr);
+ u16 (*read16)(struct rtw_dev *rtwdev, u32 addr);
+ u32 (*read32)(struct rtw_dev *rtwdev, u32 addr);
+ void (*write8)(struct rtw_dev *rtwdev, u32 addr, u8 val);
+ void (*write16)(struct rtw_dev *rtwdev, u32 addr, u16 val);
+ void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val);
+};
+
+static inline int rtw_hci_tx(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb)
+{
+ return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb);
+}
+
+static inline int rtw_hci_setup(struct rtw_dev *rtwdev)
+{
+ return rtwdev->hci.ops->setup(rtwdev);
+}
+
+static inline int rtw_hci_start(struct rtw_dev *rtwdev)
+{
+ return rtwdev->hci.ops->start(rtwdev);
+}
+
+static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
+{
+ rtwdev->hci.ops->stop(rtwdev);
+}
+
+static inline int
+rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+{
+ return rtwdev->hci.ops->write_data_rsvd_page(rtwdev, buf, size);
+}
+
+static inline int
+rtw_hci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+{
+ return rtwdev->hci.ops->write_data_h2c(rtwdev, buf, size);
+}
+
+static inline u8 rtw_read8(struct rtw_dev *rtwdev, u32 addr)
+{
+ return rtwdev->hci.ops->read8(rtwdev, addr);
+}
+
+static inline u16 rtw_read16(struct rtw_dev *rtwdev, u32 addr)
+{
+ return rtwdev->hci.ops->read16(rtwdev, addr);
+}
+
+static inline u32 rtw_read32(struct rtw_dev *rtwdev, u32 addr)
+{
+ return rtwdev->hci.ops->read32(rtwdev, addr);
+}
+
+static inline void rtw_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
+{
+ rtwdev->hci.ops->write8(rtwdev, addr, val);
+}
+
+static inline void rtw_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
+{
+ rtwdev->hci.ops->write16(rtwdev, addr, val);
+}
+
+static inline void rtw_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
+{
+ rtwdev->hci.ops->write32(rtwdev, addr, val);
+}
+
+static inline void rtw_write8_set(struct rtw_dev *rtwdev, u32 addr, u8 bit)
+{
+ u8 val;
+
+ val = rtw_read8(rtwdev, addr);
+ rtw_write8(rtwdev, addr, val | bit);
+}
+
+static inline void rtw_writ16_set(struct rtw_dev *rtwdev, u32 addr, u16 bit)
+{
+ u16 val;
+
+ val = rtw_read16(rtwdev, addr);
+ rtw_write16(rtwdev, addr, val | bit);
+}
+
+static inline void rtw_write32_set(struct rtw_dev *rtwdev, u32 addr, u32 bit)
+{
+ u32 val;
+
+ val = rtw_read32(rtwdev, addr);
+ rtw_write32(rtwdev, addr, val | bit);
+}
+
+static inline void rtw_write8_clr(struct rtw_dev *rtwdev, u32 addr, u8 bit)
+{
+ u8 val;
+
+ val = rtw_read8(rtwdev, addr);
+ rtw_write8(rtwdev, addr, val & ~bit);
+}
+
+static inline void rtw_write16_clr(struct rtw_dev *rtwdev, u32 addr, u16 bit)
+{
+ u16 val;
+
+ val = rtw_read16(rtwdev, addr);
+ rtw_write16(rtwdev, addr, val & ~bit);
+}
+
+static inline void rtw_write32_clr(struct rtw_dev *rtwdev, u32 addr, u32 bit)
+{
+ u32 val;
+
+ val = rtw_read32(rtwdev, addr);
+ rtw_write32(rtwdev, addr, val & ~bit);
+}
+
+static inline u32
+rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+ u32 addr, u32 mask)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&rtwdev->rf_lock, flags);
+ val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
+ spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
+
+ return val;
+}
+
+static inline void
+rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+ u32 addr, u32 mask, u32 data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtwdev->rf_lock, flags);
+ rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
+ spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
+}
+
+static inline u32
+rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
+{
+ u32 shift = __ffs(mask);
+ u32 orig;
+ u32 ret;
+
+ orig = rtw_read32(rtwdev, addr);
+ ret = (orig & mask) >> shift;
+
+ return ret;
+}
+
+static inline void
+rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
+{
+ u32 shift = __ffs(mask);
+ u32 orig;
+ u32 set;
+
+ WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr);
+
+ orig = rtw_read32(rtwdev, addr);
+ set = (orig & ~mask) | ((data << shift) & mask);
+ rtw_write32(rtwdev, addr, set);
+}
+
+static inline void
+rtw_write8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u8 data)
+{
+ u32 shift;
+ u8 orig, set;
+
+ mask &= 0xff;
+ shift = __ffs(mask);
+
+ orig = rtw_read8(rtwdev, addr);
+ set = (orig & ~mask) | ((data << shift) & mask);
+ rtw_write8(rtwdev, addr, set);
+}
+
+static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev)
+{
+ return rtwdev->hci.type;
+}
+
+#endif