// 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>
*
* Based on rtw88/pci.c:
* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include "main.h"
#include "debug.h"
#include "fw.h"
#include "ps.h"
#include "reg.h"
#include "rx.h"
#include "sdio.h"
#include "tx.h"
#define RTW_SDIO_INDIRECT_RW_RETRIES 50
static bool rtw_sdio_is_bus_addr(u32 addr)
{
return !!(addr & RTW_SDIO_BUS_MSK);
}
static bool rtw_sdio_bus_claim_needed(struct rtw_sdio *rtwsdio)
{
return !rtwsdio->irq_thread ||
rtwsdio->irq_thread != current;
}
static u32 rtw_sdio_to_bus_offset(struct rtw_dev *rtwdev, u32 addr)
{
switch (addr & RTW_SDIO_BUS_MSK) {
case WLAN_IOREG_OFFSET:
addr &= WLAN_IOREG_REG_MSK;
addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
REG_SDIO_CMD_ADDR_MAC_REG);
break;
case SDIO_LOCAL_OFFSET:
addr &= SDIO_LOCAL_REG_MSK;
addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
REG_SDIO_CMD_ADDR_SDIO_REG);
break;
default:
rtw_warn(rtwdev, "Cannot convert addr 0x%08x to bus offset",
addr);
}
return addr;
}
static bool rtw_sdio_use_memcpy_io(struct rtw_dev *rtwdev, u32 addr,
u8 alignment)
{
return IS_ALIGNED(addr, alignment) &&
test_bit(RTW_FLAG_POWERON, rtwdev->flags);
}
static void rtw_sdio_writel(struct rtw_dev *rtwdev, u32 val, u32 addr,
int *err_ret)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
u8 buf[