// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
*******************************************************************************/
#include <drv_types.h>
#include <rtl8723b_hal.h>
/* */
/* Description: */
/* The following mapping is for SDIO host local register space. */
/* */
/* Creadted by Roger, 2011.01.31. */
/* */
static void hal_sdio_get_cmd_addr_8723b(
struct adapter *adapter,
u8 device_id,
u32 addr,
u32 *cmdaddr
)
{
switch (device_id) {
case SDIO_LOCAL_DEVICE_ID:
*cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK));
break;
case WLAN_IOREG_DEVICE_ID:
*cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK));
break;
case WLAN_TX_HIQ_DEVICE_ID:
*cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case WLAN_TX_MIQ_DEVICE_ID:
*cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case WLAN_TX_LOQ_DEVICE_ID:
*cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case WLAN_RX0FF_DEVICE_ID:
*cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
break;
default:
break;
}
}
static u8 get_deviceid(u32 addr)
{
u8 devide_id;
u16 pseudo_id;
pseudo_id = (u16)(addr >> 16);
switch (pseudo_id) {
case 0x1025:
devide_id = SDIO_LOCAL_DEVICE_ID;
break;
case 0x1026:
devide_id = WLAN_IOREG_DEVICE_ID;
break;
case 0x1031:
devide_id = WLAN_TX_HIQ_DEVICE_ID;
break;
case 0x1032:
devide_id = WLAN_TX_MIQ_DEVICE_ID;
break;
case 0x1033:
devide_id = WLAN_TX_LOQ_DEVICE_ID;
break;
case 0x1034:
devide_id = WLAN_RX0FF_DEVICE_ID;
break;
default:
devide_id = WLAN_IOREG_DEVICE_ID;
break;
}
return devide_id;
}
static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
{
u8 device_id;
u16 offset;
u32 ftaddr;
device_id = get_deviceid(addr);
offset = 0;
switch (device_id) {
case SDIO_LOCAL_DEVICE_ID:
offset = addr & SDIO_LOCAL_MSK;
break;
case WLAN_TX_HIQ_DEVICE_ID:
case WLAN_TX_MIQ_DEVICE_ID:
case WLAN_TX_LOQ_DEVICE_ID:
offset = addr & WLAN_FIFO_MSK;
break;
case WLAN_RX0FF_DEVICE_ID:
offset = addr & WLAN_RX0FF_MSK;
break;
case WLAN_IOREG_DEVICE_ID:
default:
device_id = WLAN_IOREG_DEVICE_ID;
offset = addr & WLAN_IOREG_MSK;
break;
}
ftaddr = (device_id << 13) | offset;
if (pdevice_id)
*pdevice_id = device_id;
if (poffset)
*poffset = offset;
return ftaddr;
}
static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr)
{
u32 ftaddr;
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
return sd_read8(intfhdl, ftaddr, NULL);
}
static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr)
{
u32 ftaddr;
__le16 le_tmp;
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
return le16_to_cpu(le_tmp);
}
static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr)
{
struct adapter *adapter;
u8 mac_pwr_ctrl_on;
u8 device_id;
u16 offset;
u32 ftaddr;
u8 shift;
u32 val;
s32 __maybe_unused err;
__le32 le_tmp;
adapter = intfhdl->padapter;
ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
if (
((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
(!mac_pwr_ctrl_on) ||
(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
) {
err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
return le32_to_cpu(le_tmp);
}
/* 4 bytes alignment */
shift = ftaddr & 0x3;
if (shift == 0) {
val = sd_read32(intfhdl, ftaddr, NULL);
} else {
u8 *tmpbuf;
tmpbuf = rtw_malloc(8);
if (!tmpbuf)
return SDIO_ERR_VAL32;
ftaddr &= ~(u16)0x3;
sd_read(intfhdl, ftaddr, 8, tmpbuf);
memcpy(&le_tmp, tmpbuf + shift, 4);
val = le32_to_cpu(le_tmp);
kfree(tmpbuf);
}
return val;
}
static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
{
struct adapter *adapter;
u8 mac_pwr_ctrl_on;
u8 device_id;
u16 offset;
u32 ftaddr;
u8 shift;
s32 err;
adapter = intfhdl->padapter;
err = 0;
ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
if (
((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
(!mac_pwr_ctrl_on)