// SPDX-License-Identifier: GPL-2.0-only
/*
* Radio tuning for RTL8225 on RTL8187
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
*
* Magic delays, register offsets, and phy value tables below are
* taken from the original r8187 driver sources. Thanks to Realtek
* for their support!
*/
#include <linux/usb.h>
#include <net/mac80211.h>
#include "rtl8187.h"
#include "rtl8225.h"
u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
u8 *addr, u8 idx)
{
u8 val;
mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits8, sizeof(val), 500);
val = priv->io_dmabuf->bits8;
mutex_unlock(&priv->io_mutex);
return val;
}
u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
__le16 *addr, u8 idx)
{
__le16 val;
mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits16, sizeof(val), 500);
val = priv->io_dmabuf->bits16;
mutex_unlock(&priv->io_mutex);
return le16_to_cpu(val);
}
u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
__le32 *addr, u8 idx)
{
__le32 val;
mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits32, sizeof(val), 500);
val = priv->io_dmabuf->bits32;
mutex_unlock(&priv->io_mutex);
return le32_to_cpu(val);
}
void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
u8 *addr, u8 val, u8 idx)
{
mutex_lock(&priv->io_mutex);
priv->io_dmabuf->bits8 = val;
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits8, sizeof(val), 500);
mutex_unlock(&priv->io_mutex);
}
void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
__le16 *addr, u16 val, u8 idx)
{
mutex_lock(&priv->io_mutex);
priv->io_dmabuf->bits16 = cpu_to_le16(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits16, sizeof(val), 500);
mutex_unlock(&priv->io_mutex);
}
void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
__le32 *addr, u32 val, u8 idx)
{
mutex_lock(&priv->io_mutex);
priv->io_dmabuf->bits32 = cpu_to_le32(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, idx & 0x03,
&priv->io_dmabuf->bits32, sizeof(val), 500);
mutex_unlock(&priv->io_mutex);
}
static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg84, reg82;
u32 bangdata;
int i;
bangdata = (data << 4) | (addr & 0xf);
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
udelay(10);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
udelay(10);
for (i = 15; i >= 0; i--) {
u16 r