linux/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3/*
   4 * Radio tuning for GCT GRF5101 on RTL8180
   5 *
   6 * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
   7 *
   8 * Code from the BSD driver and the rtl8181 project have been
   9 * very useful to understand certain things
  10 *
  11 * I want to thanks the Authors of such projects and the Ndiswrapper
  12 * project Authors.
  13 *
  14 * A special Big Thanks also is for all people who donated me cards,
  15 * making possible the creation of the original rtl8180 driver
  16 * from which this code is derived!
  17 */
  18
  19#include <linux/pci.h>
  20#include <linux/delay.h>
  21#include <net/mac80211.h>
  22
  23#include "rtl8180.h"
  24#include "grf5101.h"
  25
  26static const int grf5101_encode[] = {
  27        0x0, 0x8, 0x4, 0xC,
  28        0x2, 0xA, 0x6, 0xE,
  29        0x1, 0x9, 0x5, 0xD,
  30        0x3, 0xB, 0x7, 0xF
  31};
  32
  33static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data)
  34{
  35        struct rtl8180_priv *priv = dev->priv;
  36        u32 phy_config;
  37
  38        phy_config =  grf5101_encode[(data >> 8) & 0xF];
  39        phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4;
  40        phy_config |= grf5101_encode[data & 0xF] << 8;
  41        phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12;
  42        phy_config |= (addr & 1) << 16;
  43        phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24;
  44
  45        /* MAC will bang bits to the chip */
  46        phy_config |= 0x90000000;
  47
  48        rtl818x_iowrite32(priv,
  49                (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
  50
  51        msleep(3);
  52}
  53
  54static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
  55{
  56        struct rtl8180_priv *priv = dev->priv;
  57        u8 ant = GRF5101_ANTENNA;
  58
  59        if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
  60                ant |= BB_ANTENNA_B;
  61
  62        if (chan == 14)
  63                ant |= BB_ANTATTEN_CHAN14;
  64
  65        rtl8180_write_phy(dev, 0x10, ant);
  66}
  67
  68static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq)
  69{
  70        if (agc > 60)
  71                return 65;
  72
  73        /* TODO(?): just return agc (or agc + 5) to avoid mult / div */
  74        return 65 * agc / 60;
  75}
  76
  77static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
  78                                   struct ieee80211_conf *conf)
  79{
  80        struct rtl8180_priv *priv = dev->priv;
  81        int channel =
  82                ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
  83        u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
  84        u32 chan = channel - 1;
  85
  86        /* set TX power */
  87        write_grf5101(dev, 0x15, 0x0);
  88        write_grf5101(dev, 0x06, txpw);
  89        write_grf5101(dev, 0x15, 0x10);
  90        write_grf5101(dev, 0x15, 0x0);
  91
  92        /* set frequency */
  93        write_grf5101(dev, 0x07, 0x0);
  94        write_grf5101(dev, 0x0B, chan);
  95        write_grf5101(dev, 0x07, 0x1000);
  96
  97        grf5101_write_phy_antenna(dev, channel);
  98}
  99
 100static void grf5101_rf_stop(struct ieee80211_hw *dev)
 101{
 102        struct rtl8180_priv *priv = dev->priv;
 103        u32 anaparam;
 104
 105        anaparam = priv->anaparam;
 106        anaparam &= 0x000fffff;
 107        anaparam |= 0x3f900000;
 108        rtl8180_set_anaparam(priv, anaparam);
 109
 110        write_grf5101(dev, 0x07, 0x0);
 111        write_grf5101(dev, 0x1f, 0x45);
 112        write_grf5101(dev, 0x1f, 0x5);
 113        write_grf5101(dev, 0x00, 0x8e4);
 114}
 115
 116static void grf5101_rf_init(struct ieee80211_hw *dev)
 117{
 118        struct rtl8180_priv *priv = dev->priv;
 119
 120        rtl8180_set_anaparam(priv, priv->anaparam);
 121
 122        write_grf5101(dev, 0x1f, 0x0);
 123        write_grf5101(dev, 0x1f, 0x0);
 124        write_grf5101(dev, 0x1f, 0x40);
 125        write_grf5101(dev, 0x1f, 0x60);
 126        write_grf5101(dev, 0x1f, 0x61);
 127        write_grf5101(dev, 0x1f, 0x61);
 128        write_grf5101(dev, 0x00, 0xae4);
 129        write_grf5101(dev, 0x1f, 0x1);
 130        write_grf5101(dev, 0x1f, 0x41);
 131        write_grf5101(dev, 0x1f, 0x61);
 132
 133        write_grf5101(dev, 0x01, 0x1a23);
 134        write_grf5101(dev, 0x02, 0x4971);
 135        write_grf5101(dev, 0x03, 0x41de);
 136        write_grf5101(dev, 0x04, 0x2d80);
 137        write_grf5101(dev, 0x05, 0x68ff);       /* 0x61ff original value */
 138        write_grf5101(dev, 0x06, 0x0);
 139        write_grf5101(dev, 0x07, 0x0);
 140        write_grf5101(dev, 0x08, 0x7533);
 141        write_grf5101(dev, 0x09, 0xc401);
 142        write_grf5101(dev, 0x0a, 0x0);
 143        write_grf5101(dev, 0x0c, 0x1c7);
 144        write_grf5101(dev, 0x0d, 0x29d3);
 145        write_grf5101(dev, 0x0e, 0x2e8);
 146        write_grf5101(dev, 0x10, 0x192);
 147        write_grf5101(dev, 0x11, 0x248);
 148        write_grf5101(dev, 0x12, 0x0);
 149        write_grf5101(dev, 0x13, 0x20c4);
 150        write_grf5101(dev, 0x14, 0xf4fc);
 151        write_grf5101(dev, 0x15, 0x0);
 152        write_grf5101(dev, 0x16, 0x1500);
 153
 154        write_grf5101(dev, 0x07, 0x1000);
 155
 156        /* baseband configuration */
 157        rtl8180_write_phy(dev, 0, 0xa8);
 158        rtl8180_write_phy(dev, 3, 0x0);
 159        rtl8180_write_phy(dev, 4, 0xc0);
 160        rtl8180_write_phy(dev, 5, 0x90);
 161        rtl8180_write_phy(dev, 6, 0x1e);
 162        rtl8180_write_phy(dev, 7, 0x64);
 163
 164        grf5101_write_phy_antenna(dev, 1);
 165
 166        rtl8180_write_phy(dev, 0x11, 0x88);
 167
 168        if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
 169            RTL818X_CONFIG2_ANTENNA_DIV)
 170                rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */
 171        else
 172                rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */
 173
 174        rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
 175
 176        rtl8180_write_phy(dev, 0x19, 0x0);
 177        rtl8180_write_phy(dev, 0x1a, 0xa0);
 178        rtl8180_write_phy(dev, 0x1b, 0x44);
 179}
 180
 181const struct rtl818x_rf_ops grf5101_rf_ops = {
 182        .name           = "GCT",
 183        .init           = grf5101_rf_init,
 184        .stop           = grf5101_rf_stop,
 185        .set_chan       = grf5101_rf_set_channel,
 186        .calc_rssi      = grf5101_rf_calc_rssi,
 187};
 188