// SPDX-License-Identifier: GPL-2.0-only
/*
* Radio tuning for GCT GRF5101 on RTL8180
*
* Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
*
* Code from the BSD driver and the rtl8181 project have been
* very useful to understand certain things
*
* I want to thanks the Authors of such projects and the Ndiswrapper
* project Authors.
*
* A special Big Thanks also is for all people who donated me cards,
* making possible the creation of the original rtl8180 driver
* from which this code is derived!
*/
#include <linux/pci.h>
#include <linux/delay.h>
#include <net/mac80211.h>
#include "rtl8180.h"
#include "grf5101.h"
static const int grf5101_encode[] = {
0 x0, 0 x8, 0 x4, 0 xC,
0 x2, 0 xA, 0 x6, 0 xE,
0 x1, 0 x9, 0 x5, 0 xD,
0 x3, 0 xB, 0 x7, 0 xF
};
static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data)
{
struct rtl8180_priv *priv = dev->priv;
u32 phy_config;
phy_config = grf5101_encode[(data >> 8 ) & 0 xF];
phy_config |= grf5101_encode[(data >> 4 ) & 0 xF] << 4 ;
phy_config |= grf5101_encode[data & 0 xF] << 8 ;
phy_config |= grf5101_encode[(addr >> 1 ) & 0 xF] << 12 ;
phy_config |= (addr & 1 ) << 16 ;
phy_config |= grf5101_encode[(data & 0 xf000) >> 12 ] << 24 ;
/* MAC will bang bits to the chip */
phy_config |= 0 x90000000;
rtl818x_iowrite32(priv,
(__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
msleep(3 );
}
static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
{
struct rtl8180_priv *priv = dev->priv;
u8 ant = GRF5101_ANTENNA;
if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
ant |= BB_ANTENNA_B;
if (chan == 14 )
ant |= BB_ANTATTEN_CHAN14;
rtl8180_write_phy(dev, 0 x10, ant);
}
static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq)
{
if (agc > 60 )
return 65 ;
/* TODO(?): just return agc (or agc + 5) to avoid mult / div */
return 65 * agc / 60 ;
}
static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
int channel =
ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
u32 txpw = priv->channels[channel - 1 ].hw_value & 0 xFF;
u32 chan = channel - 1 ;
/* set TX power */
write_grf5101(dev, 0 x15, 0 x0);
write_grf5101(dev, 0 x06, txpw);
write_grf5101(dev, 0 x15, 0 x10);
write_grf5101(dev, 0 x15, 0 x0);
/* set frequency */
write_grf5101(dev, 0 x07, 0 x0);
write_grf5101(dev, 0 x0B, chan);
write_grf5101(dev, 0 x07, 0 x1000);
grf5101_write_phy_antenna(dev, channel);
}
static void grf5101_rf_stop(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
u32 anaparam;
anaparam = priv->anaparam;
anaparam &= 0 x000fffff;
anaparam |= 0 x3f900000;
rtl8180_set_anaparam(priv, anaparam);
write_grf5101(dev, 0 x07, 0 x0);
write_grf5101(dev, 0 x1f, 0 x45);
write_grf5101(dev, 0 x1f, 0 x5);
write_grf5101(dev, 0 x00, 0 x8e4);
}
static void grf5101_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
rtl8180_set_anaparam(priv, priv->anaparam);
write_grf5101(dev, 0 x1f, 0 x0);
write_grf5101(dev, 0 x1f, 0 x0);
write_grf5101(dev, 0 x1f, 0 x40);
write_grf5101(dev, 0 x1f, 0 x60);
write_grf5101(dev, 0 x1f, 0 x61);
write_grf5101(dev, 0 x1f, 0 x61);
write_grf5101(dev, 0 x00, 0 xae4);
write_grf5101(dev, 0 x1f, 0 x1);
write_grf5101(dev, 0 x1f, 0 x41);
write_grf5101(dev, 0 x1f, 0 x61);
write_grf5101(dev, 0 x01, 0 x1a23);
write_grf5101(dev, 0 x02, 0 x4971);
write_grf5101(dev, 0 x03, 0 x41de);
write_grf5101(dev, 0 x04, 0 x2d80);
write_grf5101(dev, 0 x05, 0 x68ff); /* 0x61ff original value */
write_grf5101(dev, 0 x06, 0 x0);
write_grf5101(dev, 0 x07, 0 x0);
write_grf5101(dev, 0 x08, 0 x7533);
write_grf5101(dev, 0 x09, 0 xc401);
write_grf5101(dev, 0 x0a, 0 x0);
write_grf5101(dev, 0 x0c, 0 x1c7);
write_grf5101(dev, 0 x0d, 0 x29d3);
write_grf5101(dev, 0 x0e, 0 x2e8);
write_grf5101(dev, 0 x10, 0 x192);
write_grf5101(dev, 0 x11, 0 x248);
write_grf5101(dev, 0 x12, 0 x0);
write_grf5101(dev, 0 x13, 0 x20c4);
write_grf5101(dev, 0 x14, 0 xf4fc);
write_grf5101(dev, 0 x15, 0 x0);
write_grf5101(dev, 0 x16, 0 x1500);
write_grf5101(dev, 0 x07, 0 x1000);
/* baseband configuration */
rtl8180_write_phy(dev, 0 , 0 xa8);
rtl8180_write_phy(dev, 3 , 0 x0);
rtl8180_write_phy(dev, 4 , 0 xc0);
rtl8180_write_phy(dev, 5 , 0 x90);
rtl8180_write_phy(dev, 6 , 0 x1e);
rtl8180_write_phy(dev, 7 , 0 x64);
grf5101_write_phy_antenna(dev, 1 );
rtl8180_write_phy(dev, 0 x11, 0 x88);
if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
RTL818X_CONFIG2_ANTENNA_DIV)
rtl8180_write_phy(dev, 0 x12, 0 xc0); /* enable ant diversity */
else
rtl8180_write_phy(dev, 0 x12, 0 x40); /* disable ant diversity */
rtl8180_write_phy(dev, 0 x13, 0 x90 | priv->csthreshold);
rtl8180_write_phy(dev, 0 x19, 0 x0);
rtl8180_write_phy(dev, 0 x1a, 0 xa0);
rtl8180_write_phy(dev, 0 x1b, 0 x44);
}
const struct rtl818x_rf_ops grf5101_rf_ops = {
.name = "GCT" ,
.init = grf5101_rf_init,
.stop = grf5101_rf_stop,
.set_chan = grf5101_rf_set_channel,
.calc_rssi = grf5101_rf_calc_rssi,
};
Messung V0.5 in Prozent C=96 H=91 G=93
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland