Commit 65371a3f authored by Martin Blumenstingl's avatar Martin Blumenstingl Committed by Kalle Valo

wifi: rtw88: sdio: Add HCI implementation for SDIO based chipsets

Add a sub-driver for SDIO based chipsets which implements the following
functionality:
- register accessors for 8, 16 and 32 bits for all states of the card
  (including usage of 4x 8 bit access for one 32 bit buffer if the card
  is not fully powered on yet - or if it's fully powered on then 1x 32
  bit access is used)
- checking whether there's space in the TX FIFO queue to transmit data
- transfers from the host to the device for actual network traffic,
  reserved pages (for firmware download) and H2C (host-to-card)
  transfers
- receiving data from the device
- deep power saving state

The transmit path is optimized so DMA-capable SDIO host controllers can
directly use the buffers provided because the buffer's physical
addresses are 8 byte aligned.

The receive path is prepared to support RX aggregation where the
chipset combines multiple MAC frames into one bigger buffer to reduce
SDIO transfer overhead.
Co-developed-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Reviewed-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230405200729.632435-3-martin.blumenstingl@googlemail.com
parent 6a925660
...@@ -16,6 +16,9 @@ config RTW88_CORE ...@@ -16,6 +16,9 @@ config RTW88_CORE
config RTW88_PCI config RTW88_PCI
tristate tristate
config RTW88_SDIO
tristate
config RTW88_USB config RTW88_USB
tristate tristate
......
...@@ -59,5 +59,8 @@ rtw88_8821cu-objs := rtw8821cu.o ...@@ -59,5 +59,8 @@ rtw88_8821cu-objs := rtw8821cu.o
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
rtw88_pci-objs := pci.o rtw88_pci-objs := pci.o
obj-$(CONFIG_RTW88_SDIO) += rtw88_sdio.o
rtw88_sdio-objs := sdio.o
obj-$(CONFIG_RTW88_USB) += rtw88_usb.o obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
rtw88_usb-objs := usb.o rtw88_usb-objs := usb.o
...@@ -24,6 +24,7 @@ enum rtw_debug_mask { ...@@ -24,6 +24,7 @@ enum rtw_debug_mask {
RTW_DBG_ADAPTIVITY = 0x00008000, RTW_DBG_ADAPTIVITY = 0x00008000,
RTW_DBG_HW_SCAN = 0x00010000, RTW_DBG_HW_SCAN = 0x00010000,
RTW_DBG_STATE = 0x00020000, RTW_DBG_STATE = 0x00020000,
RTW_DBG_SDIO = 0x00040000,
RTW_DBG_ALL = 0xffffffff RTW_DBG_ALL = 0xffffffff
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "reg.h" #include "reg.h"
#include "fw.h" #include "fw.h"
#include "debug.h" #include "debug.h"
#include "sdio.h"
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
u8 primary_ch_idx) u8 primary_ch_idx)
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define RTW_HW_PORT_NUM 5 #define RTW_HW_PORT_NUM 5
#define cut_version_to_mask(cut) (0x1 << ((cut) + 1)) #define cut_version_to_mask(cut) (0x1 << ((cut) + 1))
#define SDIO_LOCAL_OFFSET 0x10250000
#define DDMA_POLLING_COUNT 1000 #define DDMA_POLLING_COUNT 1000
#define C2H_PKT_BUF 256 #define C2H_PKT_BUF 256
#define REPORT_BUF 128 #define REPORT_BUF 128
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#define BIT_LTE_MUX_CTRL_PATH BIT(26) #define BIT_LTE_MUX_CTRL_PATH BIT(26)
#define REG_HCI_OPT_CTRL 0x0074 #define REG_HCI_OPT_CTRL 0x0074
#define BIT_USB_SUS_DIS BIT(8) #define BIT_USB_SUS_DIS BIT(8)
#define BIT_SDIO_PAD_E5 BIT(18)
#define REG_AFE_CTRL_4 0x0078 #define REG_AFE_CTRL_4 0x0078
#define BIT_CK320M_AFE_EN BIT(4) #define BIT_CK320M_AFE_EN BIT(4)
...@@ -185,6 +186,9 @@ ...@@ -185,6 +186,9 @@
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) (((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
#define REG_TXDMA_PQ_MAP 0x010C #define REG_TXDMA_PQ_MAP 0x010C
#define BIT_RXDMA_ARBBW_EN BIT(0) #define BIT_RXDMA_ARBBW_EN BIT(0)
#define BIT_RXSHFT_EN BIT(1)
#define BIT_RXDMA_AGG_EN BIT(2)
#define BIT_TXDMA_BW_EN BIT(3)
#define BIT_SHIFT_TXDMA_BEQ_MAP 8 #define BIT_SHIFT_TXDMA_BEQ_MAP 8
#define BIT_MASK_TXDMA_BEQ_MAP 0x3 #define BIT_MASK_TXDMA_BEQ_MAP 0x3
#define BIT_TXDMA_BEQ_MAP(x) \ #define BIT_TXDMA_BEQ_MAP(x) \
...@@ -283,10 +287,18 @@ ...@@ -283,10 +287,18 @@
#define REG_H2C_TAIL 0x0248 #define REG_H2C_TAIL 0x0248
#define REG_H2C_READ_ADDR 0x024C #define REG_H2C_READ_ADDR 0x024C
#define REG_H2C_INFO 0x0254 #define REG_H2C_INFO 0x0254
#define REG_RXDMA_AGG_PG_TH 0x0280
#define BIT_RXDMA_AGG_PG_TH GENMASK(7, 0)
#define BIT_DMA_AGG_TO_V1 GENMASK(15, 8)
#define BIT_EN_PRE_CALC BIT(29)
#define REG_RXPKT_NUM 0x0284 #define REG_RXPKT_NUM 0x0284
#define BIT_RXDMA_REQ BIT(19) #define BIT_RXDMA_REQ BIT(19)
#define BIT_RW_RELEASE BIT(18) #define BIT_RW_RELEASE BIT(18)
#define BIT_RXDMA_IDLE BIT(17) #define BIT_RXDMA_IDLE BIT(17)
#define REG_RXDMA_STATUS 0x0288
#define REG_RXDMA_DPR 0x028C
#define REG_RXDMA_MODE 0x0290
#define BIT_DMA_MODE BIT(1)
#define REG_RXPKTNUM 0x02B0 #define REG_RXPKTNUM 0x02B0
#define REG_INT_MIG 0x0304 #define REG_INT_MIG 0x0304
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright (C) 2021 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
* Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@gmail.com>
*/
#ifndef __REG_SDIO_H_
#define __REG_SDIO_H_
/* I/O bus domain address mapping */
#define SDIO_LOCAL_OFFSET 0x10250000
#define WLAN_IOREG_OFFSET 0x10260000
#define FIRMWARE_FIFO_OFFSET 0x10270000
#define TX_HIQ_OFFSET 0x10310000
#define TX_MIQ_OFFSET 0x10320000
#define TX_LOQ_OFFSET 0x10330000
#define TX_EPQ_OFFSET 0x10350000
#define RX_RX0FF_OFFSET 0x10340000
#define RTW_SDIO_BUS_MSK 0xffff0000
#define SDIO_LOCAL_REG_MSK 0x00000fff
#define WLAN_IOREG_REG_MSK 0x0000ffff
/* SDIO Tx Control */
#define REG_SDIO_TX_CTRL (SDIO_LOCAL_OFFSET + 0x0000)
/*SDIO status timeout*/
#define REG_SDIO_TIMEOUT (SDIO_LOCAL_OFFSET + 0x0002)
/* SDIO Host Interrupt Mask */
#define REG_SDIO_HIMR (SDIO_LOCAL_OFFSET + 0x0014)
#define REG_SDIO_HIMR_RX_REQUEST BIT(0)
#define REG_SDIO_HIMR_AVAL BIT(1)
#define REG_SDIO_HIMR_TXERR BIT(2)
#define REG_SDIO_HIMR_RXERR BIT(3)
#define REG_SDIO_HIMR_TXFOVW BIT(4)
#define REG_SDIO_HIMR_RXFOVW BIT(5)
#define REG_SDIO_HIMR_TXBCNOK BIT(6)
#define REG_SDIO_HIMR_TXBCNERR BIT(7)
#define REG_SDIO_HIMR_BCNERLY_INT BIT(16)
#define REG_SDIO_HIMR_C2HCMD BIT(17)
#define REG_SDIO_HIMR_CPWM1 BIT(18)
#define REG_SDIO_HIMR_CPWM2 BIT(19)
#define REG_SDIO_HIMR_HSISR_IND BIT(20)
#define REG_SDIO_HIMR_GTINT3_IND BIT(21)
#define REG_SDIO_HIMR_GTINT4_IND BIT(22)
#define REG_SDIO_HIMR_PSTIMEOUT BIT(23)
#define REG_SDIO_HIMR_OCPINT BIT(24)
#define REG_SDIO_HIMR_ATIMEND BIT(25)
#define REG_SDIO_HIMR_ATIMEND_E BIT(26)
#define REG_SDIO_HIMR_CTWEND BIT(27)
/* the following two are RTL8188 SDIO Specific */
#define REG_SDIO_HIMR_MCU_ERR BIT(28)
#define REG_SDIO_HIMR_TSF_BIT32_TOGGLE BIT(29)
/* SDIO Host Interrupt Service Routine */
#define REG_SDIO_HISR (SDIO_LOCAL_OFFSET + 0x0018)
#define REG_SDIO_HISR_RX_REQUEST BIT(0)
#define REG_SDIO_HISR_AVAL BIT(1)
#define REG_SDIO_HISR_TXERR BIT(2)
#define REG_SDIO_HISR_RXERR BIT(3)
#define REG_SDIO_HISR_TXFOVW BIT(4)
#define REG_SDIO_HISR_RXFOVW BIT(5)
#define REG_SDIO_HISR_TXBCNOK BIT(6)
#define REG_SDIO_HISR_TXBCNERR BIT(7)
#define REG_SDIO_HISR_BCNERLY_INT BIT(16)
#define REG_SDIO_HISR_C2HCMD BIT(17)
#define REG_SDIO_HISR_CPWM1 BIT(18)
#define REG_SDIO_HISR_CPWM2 BIT(19)
#define REG_SDIO_HISR_HSISR_IND BIT(20)
#define REG_SDIO_HISR_GTINT3_IND BIT(21)
#define REG_SDIO_HISR_GTINT4_IND BIT(22)
#define REG_SDIO_HISR_PSTIMEOUT BIT(23)
#define REG_SDIO_HISR_OCPINT BIT(24)
#define REG_SDIO_HISR_ATIMEND BIT(25)
#define REG_SDIO_HISR_ATIMEND_E BIT(26)
#define REG_SDIO_HISR_CTWEND BIT(27)
/* the following two are RTL8188 SDIO Specific */
#define REG_SDIO_HISR_MCU_ERR BIT(28)
#define REG_SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
/* HCI Current Power Mode */
#define REG_SDIO_HCPWM (SDIO_LOCAL_OFFSET + 0x0019)
/* RXDMA Request Length */
#define REG_SDIO_RX0_REQ_LEN (SDIO_LOCAL_OFFSET + 0x001C)
/* OQT Free Page */
#define REG_SDIO_OQT_FREE_PG (SDIO_LOCAL_OFFSET + 0x001E)
/* Free Tx Buffer Page */
#define REG_SDIO_FREE_TXPG (SDIO_LOCAL_OFFSET + 0x0020)
/* HCI Current Power Mode 1 */
#define REG_SDIO_HCPWM1 (SDIO_LOCAL_OFFSET + 0x0024)
/* HCI Current Power Mode 2 */
#define REG_SDIO_HCPWM2 (SDIO_LOCAL_OFFSET + 0x0026)
/* Free Tx Page Sequence */
#define REG_SDIO_FREE_TXPG_SEQ (SDIO_LOCAL_OFFSET + 0x0028)
/* HTSF Information */
#define REG_SDIO_HTSFR_INFO (SDIO_LOCAL_OFFSET + 0x0030)
#define REG_SDIO_HCPWM1_V2 (SDIO_LOCAL_OFFSET + 0x0038)
/* H2C */
#define REG_SDIO_H2C (SDIO_LOCAL_OFFSET + 0x0060)
/* HCI Request Power Mode 1 */
#define REG_SDIO_HRPWM1 (SDIO_LOCAL_OFFSET + 0x0080)
/* HCI Request Power Mode 2 */
#define REG_SDIO_HRPWM2 (SDIO_LOCAL_OFFSET + 0x0082)
/* HCI Power Save Clock */
#define REG_SDIO_HPS_CLKR (SDIO_LOCAL_OFFSET + 0x0084)
/* SDIO HCI Suspend Control */
#define REG_SDIO_HSUS_CTRL (SDIO_LOCAL_OFFSET + 0x0086)
#define BIT_HCI_SUS_REQ BIT(0)
#define BIT_HCI_RESUME_RDY BIT(1)
/* SDIO Host Extension Interrupt Mask Always */
#define REG_SDIO_HIMR_ON (SDIO_LOCAL_OFFSET + 0x0090)
/* SDIO Host Extension Interrupt Status Always */
#define REG_SDIO_HISR_ON (SDIO_LOCAL_OFFSET + 0x0091)
#define REG_SDIO_INDIRECT_REG_CFG (SDIO_LOCAL_OFFSET + 0x0040)
#define BIT_SDIO_INDIRECT_REG_CFG_WORD BIT(16)
#define BIT_SDIO_INDIRECT_REG_CFG_DWORD BIT(17)
#define BIT_SDIO_INDIRECT_REG_CFG_WRITE BIT(18)
#define BIT_SDIO_INDIRECT_REG_CFG_READ BIT(19)
#define BIT_SDIO_INDIRECT_REG_CFG_UNK20 BIT(20)
#define REG_SDIO_INDIRECT_REG_DATA (SDIO_LOCAL_OFFSET + 0x0044)
/* Sdio Address for SDIO Local Reg, TRX FIFO, MAC Reg */
#define REG_SDIO_CMD_ADDR_MSK GENMASK(16, 13)
#define REG_SDIO_CMD_ADDR_SDIO_REG 0
#define REG_SDIO_CMD_ADDR_MAC_REG 8
#define REG_SDIO_CMD_ADDR_TXFF_HIGH 4
#define REG_SDIO_CMD_ADDR_TXFF_LOW 6
#define REG_SDIO_CMD_ADDR_TXFF_NORMAL 5
#define REG_SDIO_CMD_ADDR_TXFF_EXTRA 7
#define REG_SDIO_CMD_ADDR_RXFF 7
#define RTW_SDIO_BLOCK_SIZE 512
#define RTW_SDIO_ADDR_RX_RX0FF_GEN(_id) (0x0e000 | ((_id) & 0x3))
#define RTW_SDIO_DATA_PTR_ALIGN 8
struct sdio_func;
struct sdio_device_id;
struct rtw_sdio_tx_data {
u8 sn;
};
struct rtw_sdio_work_data {
struct work_struct work;
struct rtw_dev *rtwdev;
};
struct rtw_sdio {
struct sdio_func *sdio_func;
u32 irq_mask;
u8 rx_addr;
bool sdio3_bus_mode;
void *irq_thread;
struct workqueue_struct *txwq;
struct rtw_sdio_work_data *tx_handler_data;
struct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM];
};
extern const struct dev_pm_ops rtw_sdio_pm_ops;
int rtw_sdio_probe(struct sdio_func *sdio_func,
const struct sdio_device_id *id);
void rtw_sdio_remove(struct sdio_func *sdio_func);
void rtw_sdio_shutdown(struct device *dev);
static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
return rtwsdio->sdio3_bus_mode;
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment