Commit 9496d62f authored by Chin-Yen Lee's avatar Chin-Yen Lee Committed by Kalle Valo

wifi: rtw89: pci: use DBI function for 8852AE/8852BE/8851BE

Sometimes driver can't use kernel API pci_read/write_config_byte
to access the PCI config space of above address 0x100 due to
the negotiated PCI setting. 8852AE/8852BE/8851BE provide another
way called DBI function, which belongs to WiFi mac and could
access all PCI config space for this case.

Link: https://lore.kernel.org/linux-wireless/79fe81b7db7148b9a7da2353c16d70fb@realtek.com/T/#tSigned-off-by: default avatarChin-Yen Lee <timlee@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240103012346.6822-1-pkshih@realtek.com
parent 3fbf6120
......@@ -1907,22 +1907,87 @@ static int rtw89_write16_mdio_clr(struct rtw89_dev *rtwdev, u8 addr, u16 mask, u
return 0;
}
static int rtw89_dbi_write8(struct rtw89_dev *rtwdev, u16 addr, u8 data)
{
u16 addr_2lsb = addr & B_AX_DBI_2LSB;
u16 write_addr;
u8 flag;
int ret;
write_addr = addr & B_AX_DBI_ADDR_MSK;
write_addr |= u16_encode_bits(BIT(addr_2lsb), B_AX_DBI_WREN_MSK);
rtw89_write8(rtwdev, R_AX_DBI_WDATA + addr_2lsb, data);
rtw89_write16(rtwdev, R_AX_DBI_FLAG, write_addr);
rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_WFLAG >> 16);
ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10,
10 * RTW89_PCI_WR_RETRY_CNT, false,
rtwdev, R_AX_DBI_FLAG + 2);
if (ret)
rtw89_err(rtwdev, "failed to write DBI register, addr=0x%X\n",
addr);
return ret;
}
static int rtw89_dbi_read8(struct rtw89_dev *rtwdev, u16 addr, u8 *value)
{
u16 read_addr = addr & B_AX_DBI_ADDR_MSK;
u8 flag;
int ret;
rtw89_write16(rtwdev, R_AX_DBI_FLAG, read_addr);
rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_RFLAG >> 16);
ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10,
10 * RTW89_PCI_WR_RETRY_CNT, false,
rtwdev, R_AX_DBI_FLAG + 2);
if (ret) {
rtw89_err(rtwdev, "failed to read DBI register, addr=0x%X\n",
addr);
return ret;
}
read_addr = R_AX_DBI_RDATA + (addr & 3);
*value = rtw89_read8(rtwdev, read_addr);
return 0;
}
static int rtw89_pci_write_config_byte(struct rtw89_dev *rtwdev, u16 addr,
u8 data)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
struct pci_dev *pdev = rtwpci->pdev;
int ret;
ret = pci_write_config_byte(pdev, addr, data);
if (!ret)
return 0;
return pci_write_config_byte(pdev, addr, data);
if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
ret = rtw89_dbi_write8(rtwdev, addr, data);
return ret;
}
static int rtw89_pci_read_config_byte(struct rtw89_dev *rtwdev, u16 addr,
u8 *value)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
struct pci_dev *pdev = rtwpci->pdev;
int ret;
return pci_read_config_byte(pdev, addr, value);
ret = pci_read_config_byte(pdev, addr, value);
if (!ret)
return 0;
if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
ret = rtw89_dbi_read8(rtwdev, addr, value);
return ret;
}
static int rtw89_pci_config_byte_set(struct rtw89_dev *rtwdev, u16 addr,
......
......@@ -42,6 +42,7 @@
#define B_AX_DBI_WFLAG BIT(16)
#define B_AX_DBI_WREN_MSK GENMASK(15, 12)
#define B_AX_DBI_ADDR_MSK GENMASK(11, 2)
#define B_AX_DBI_2LSB GENMASK(1, 0)
#define R_AX_DBI_WDATA 0x1094
#define R_AX_DBI_RDATA 0x1098
......
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