2007-12-25 06:24:10

by Michael Wu

[permalink] [raw]
Subject: [PATCH] rtl818x: Use RF ops tables

Unfortunately, merging the usb and pci rtl8225 rf code is currently
more pain than gain. Switch to RF ops tables to avoid symbol conflicts
when building in the rtl818x drivers.

Signed-off-by: Michael Wu <[email protected]>
---

drivers/net/wireless/rtl8180.h | 4 --
drivers/net/wireless/rtl8180_dev.c | 47 +++++----------------
drivers/net/wireless/rtl8180_grf5101.c | 15 +++++--
drivers/net/wireless/rtl8180_grf5101.h | 4 --
drivers/net/wireless/rtl8180_max2820.c | 16 +++++--
drivers/net/wireless/rtl8180_max2820.h | 4 --
drivers/net/wireless/rtl8180_rtl8225.c | 71 ++++++++++++++++++++------------
drivers/net/wireless/rtl8180_rtl8225.h | 7 ---
drivers/net/wireless/rtl8180_sa2400.c | 14 +++++-
drivers/net/wireless/rtl8180_sa2400.h | 4 --
drivers/net/wireless/rtl8187.h | 2 -
drivers/net/wireless/rtl8187_dev.c | 48 ++++++++--------------
drivers/net/wireless/rtl8187_rtl8225.c | 52 +++++++++++++++++++----
drivers/net/wireless/rtl8187_rtl8225.h | 9 ----
drivers/net/wireless/rtl818x.h | 7 +++
15 files changed, 163 insertions(+), 141 deletions(-)

diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
index 41b64cb..2cbfe3c 100644
--- a/drivers/net/wireless/rtl8180.h
+++ b/drivers/net/wireless/rtl8180.h
@@ -89,9 +89,7 @@ struct rtl8180_tx_ring {
struct rtl8180_priv {
/* common between rtl818x drivers */
struct rtl818x_csr __iomem *map;
- void (*rf_init)(struct ieee80211_hw *);
- void (*rf_stop)(struct ieee80211_hw *);
- void (*rf_set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+ const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif;
int mode;

diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index c8e24a1..07f37b0 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -375,7 +375,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C);
}

- priv->rf_init(dev);
+ priv->rf->init(dev);
if (priv->r8185)
rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
return 0;
@@ -609,7 +609,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
reg &= ~RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);

- priv->rf_stop(dev);
+ priv->rf->stop(dev);

rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
@@ -663,7 +663,7 @@ static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;

- priv->rf_set_chan(dev, conf);
+ priv->rf->set_chan(dev, conf);

return 0;
}
@@ -770,7 +770,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
unsigned int io_addr, io_len;
int err, i;
struct eeprom_93cx6 eeprom;
- const char *chip_name, *rf_name;
+ const char *chip_name, *rf_name = NULL;
u32 reg;
u16 eeprom_val;
DECLARE_MAC_BUF(mac);
@@ -900,40 +900,17 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val);
eeprom_val &= 0xFF;
switch (eeprom_val) {
- case 1:
- rf_name = "Intersil";
+ case 1: rf_name = "Intersil";
break;
- case 2:
- rf_name = "RFMD";
+ case 2: rf_name = "RFMD";
break;
- case 3:
- rf_name = "Philips";
- priv->rf_init = sa2400_rf_init;
- priv->rf_stop = sa2400_rf_stop;
- priv->rf_set_chan = sa2400_rf_set_channel;
+ case 3: priv->rf = &sa2400_rf_ops;
break;
- case 4:
- rf_name = "Maxim";
- priv->rf_init = max2820_rf_init;
- priv->rf_stop = max2820_rf_stop;
- priv->rf_set_chan = max2820_rf_set_channel;
+ case 4: priv->rf = &max2820_rf_ops;
break;
- case 5:
- rf_name = "GCT";
- priv->rf_init = grf5101_rf_init;
- priv->rf_stop = grf5101_rf_stop;
- priv->rf_set_chan = grf5101_rf_set_channel;
+ case 5: priv->rf = &grf5101_rf_ops;
break;
- case 9:
- if (rtl8225_is_z2(dev)) {
- rf_name = "RTL8225z2";
- priv->rf_init = rtl8225z2_rf_init;
- } else {
- rf_name = "RTL8225";
- priv->rf_init = rtl8225_rf_init;
- }
- priv->rf_stop = rtl8225_rf_stop;
- priv->rf_set_chan = rtl8225_rf_set_channel;
+ case 9: priv->rf = rtl8180_detect_rf(dev);
break;
case 10:
rf_name = "RTL8255";
@@ -944,7 +921,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
goto err_iounmap;
}

- if (eeprom_val < 3) {
+ if (!priv->rf) {
printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",
pci_name(pdev), rf_name);
goto err_iounmap;
@@ -997,7 +974,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,

printk(KERN_INFO "%s: hwaddr %s, %s + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
- chip_name, rf_name);
+ chip_name, priv->rf->name);

return 0;

diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
index 11e80ab..8293e19 100644
--- a/drivers/net/wireless/rtl8180_grf5101.c
+++ b/drivers/net/wireless/rtl8180_grf5101.c
@@ -69,8 +69,8 @@ static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
rtl8180_write_phy(dev, 0x10, ant);
}

-void grf5101_rf_set_channel(struct ieee80211_hw *dev,
- struct ieee80211_conf *conf)
+static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
@@ -90,7 +90,7 @@ void grf5101_rf_set_channel(struct ieee80211_hw *dev,
grf5101_write_phy_antenna(dev, chan);
}

-void grf5101_rf_stop(struct ieee80211_hw *dev)
+static void grf5101_rf_stop(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
u32 anaparam;
@@ -106,7 +106,7 @@ void grf5101_rf_stop(struct ieee80211_hw *dev)
write_grf5101(dev, 0x00, 0x8e4);
}

-void grf5101_rf_init(struct ieee80211_hw *dev)
+static void grf5101_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;

@@ -170,3 +170,10 @@ void grf5101_rf_init(struct ieee80211_hw *dev)
rtl8180_write_phy(dev, 0x1a, 0xa0);
rtl8180_write_phy(dev, 0x1b, 0x44);
}
+
+const struct rtl818x_rf_ops grf5101_rf_ops = {
+ .name = "GCT",
+ .init = grf5101_rf_init,
+ .stop = grf5101_rf_stop,
+ .set_chan = grf5101_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_grf5101.h b/drivers/net/wireless/rtl8180_grf5101.h
index 5b4a171..7664711 100644
--- a/drivers/net/wireless/rtl8180_grf5101.h
+++ b/drivers/net/wireless/rtl8180_grf5101.h
@@ -23,8 +23,6 @@

#define GRF5101_ANTENNA 0xA3

-void grf5101_rf_init(struct ieee80211_hw *);
-void grf5101_rf_stop(struct ieee80211_hw *);
-void grf5101_rf_set_channel(struct ieee80211_hw *, struct ieee80211_conf *);
+extern const struct rtl818x_rf_ops grf5101_rf_ops;

#endif /* RTL8180_GRF5101_H */
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
index c3e125f..98fe9fd 100644
--- a/drivers/net/wireless/rtl8180_max2820.c
+++ b/drivers/net/wireless/rtl8180_max2820.c
@@ -26,7 +26,7 @@
#include "rtl8180.h"
#include "rtl8180_max2820.h"

-u32 max2820_chan[] = {
+static const u32 max2820_chan[] = {
12, /* CH 1 */
17,
22,
@@ -74,7 +74,8 @@ static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan)
rtl8180_write_phy(dev, 0x10, ant);
}

-void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static void max2820_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
unsigned int chan_idx = conf ? conf->channel - 1 : 0;
@@ -89,14 +90,14 @@ void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *con
write_max2820(dev, 3, chan);
}

-void max2820_rf_stop(struct ieee80211_hw *dev)
+static void max2820_rf_stop(struct ieee80211_hw *dev)
{
rtl8180_write_phy(dev, 3, 0x8);
write_max2820(dev, 1, 0);
}


-void max2820_rf_init(struct ieee80211_hw *dev)
+static void max2820_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;

@@ -140,3 +141,10 @@ void max2820_rf_init(struct ieee80211_hw *dev)

max2820_rf_set_channel(dev, NULL);
}
+
+const struct rtl818x_rf_ops max2820_rf_ops = {
+ .name = "Maxim",
+ .init = max2820_rf_init,
+ .stop = max2820_rf_stop,
+ .set_chan = max2820_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_max2820.h b/drivers/net/wireless/rtl8180_max2820.h
index 8e27292..61cf6d1 100644
--- a/drivers/net/wireless/rtl8180_max2820.h
+++ b/drivers/net/wireless/rtl8180_max2820.h
@@ -23,8 +23,6 @@

#define MAXIM_ANTENNA 0xb3

-void max2820_rf_init(struct ieee80211_hw *);
-void max2820_rf_stop(struct ieee80211_hw *);
-void max2820_rf_set_channel(struct ieee80211_hw *, struct ieee80211_conf *);
+extern const struct rtl818x_rf_ops max2820_rf_ops;

#endif /* RTL8180_MAX2820_H */
diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c
index 09a54fd..37ac402 100644
--- a/drivers/net/wireless/rtl8180_rtl8225.c
+++ b/drivers/net/wireless/rtl8180_rtl8225.c
@@ -299,28 +299,7 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
msleep(1);
}

-int rtl8225_is_z2(struct ieee80211_hw *dev)
-{
- struct rtl8180_priv *priv = dev->priv;
- int z2 = 0;
-
- rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
- rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
- rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
- rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
- msleep(100);
-
- rtl8225_write(dev, 0, 0x1B7);
-
- if (rtl8225_read(dev, 8) == 0x588 && rtl8225_read(dev, 9) == 0x700)
- z2 = 1;
-
- rtl8225_write(dev, 0, 0x0B7);
-
- return z2;
-}
-
-void rtl8225_rf_init(struct ieee80211_hw *dev)
+static void rtl8225_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
int i;
@@ -549,7 +528,7 @@ static const u16 rtl8225z2_rxgain[] = {
0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
};

-void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
int i;
@@ -718,7 +697,7 @@ void rtl8225z2_rf_init(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
}

-void rtl8225_rf_stop(struct ieee80211_hw *dev)
+static void rtl8225_rf_stop(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
u8 reg;
@@ -734,12 +713,12 @@ void rtl8225_rf_stop(struct ieee80211_hw *dev)
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
}

-void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
- struct ieee80211_conf *conf)
+static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;

- if (priv->rf_init == rtl8225_rf_init)
+ if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, conf->channel);
else
rtl8225z2_rf_set_tx_power(dev, conf->channel);
@@ -761,3 +740,41 @@ void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
}
}
+
+static const struct rtl818x_rf_ops rtl8225_ops = {
+ .name = "rtl8225",
+ .init = rtl8225_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+static const struct rtl818x_rf_ops rtl8225z2_ops = {
+ .name = "rtl8225z2",
+ .init = rtl8225z2_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg8, reg9;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ msleep(100);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ reg8 = rtl8225_read(dev, 8);
+ reg9 = rtl8225_read(dev, 9);
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ if (reg8 != 0x588 || reg9 != 0x700)
+ return &rtl8225_ops;
+
+ return &rtl8225z2_ops;
+}
diff --git a/drivers/net/wireless/rtl8180_rtl8225.h b/drivers/net/wireless/rtl8180_rtl8225.h
index e142795..92d2b17 100644
--- a/drivers/net/wireless/rtl8180_rtl8225.h
+++ b/drivers/net/wireless/rtl8180_rtl8225.h
@@ -6,12 +6,7 @@
#define RTL8225_ANAPARAM_OFF 0xa00beb59
#define RTL8225_ANAPARAM2_OFF 0x840dec11

-int rtl8225_is_z2(struct ieee80211_hw *dev);
-
-void rtl8225_rf_init(struct ieee80211_hw *);
-void rtl8225z2_rf_init(struct ieee80211_hw *);
-void rtl8225_rf_stop(struct ieee80211_hw *);
-void rtl8225_rf_set_channel(struct ieee80211_hw *, struct ieee80211_conf *);
+const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *);

static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
u8 addr, u8 data)
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
index dea7e5a..e08ace7 100644
--- a/drivers/net/wireless/rtl8180_sa2400.c
+++ b/drivers/net/wireless/rtl8180_sa2400.c
@@ -76,7 +76,8 @@ static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)

}

-void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
@@ -92,12 +93,12 @@ void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf
write_sa2400(dev, 3, 0);
}

-void sa2400_rf_stop(struct ieee80211_hw *dev)
+static void sa2400_rf_stop(struct ieee80211_hw *dev)
{
write_sa2400(dev, 4, 0);
}

-void sa2400_rf_init(struct ieee80211_hw *dev)
+static void sa2400_rf_init(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
u32 anaparam, txconf;
@@ -191,3 +192,10 @@ void sa2400_rf_init(struct ieee80211_hw *dev)
rtl8180_write_phy(dev, 0x19, 0x0);
rtl8180_write_phy(dev, 0x1a, 0xa0);
}
+
+const struct rtl818x_rf_ops sa2400_rf_ops = {
+ .name = "Philips",
+ .init = sa2400_rf_init,
+ .stop = sa2400_rf_stop,
+ .set_chan = sa2400_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_sa2400.h b/drivers/net/wireless/rtl8180_sa2400.h
index 018bb92..a4aaa0d 100644
--- a/drivers/net/wireless/rtl8180_sa2400.h
+++ b/drivers/net/wireless/rtl8180_sa2400.h
@@ -31,8 +31,6 @@

#define SA2400_REG4_FIRDAC_SHIFT 7

-void sa2400_rf_init(struct ieee80211_hw *);
-void sa2400_rf_stop(struct ieee80211_hw *);
-void sa2400_rf_set_channel(struct ieee80211_hw *, struct ieee80211_conf *);
+extern const struct rtl818x_rf_ops sa2400_rf_ops;

#endif /* RTL8180_SA2400_H */
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index a934a46..8680a0b 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -64,7 +64,7 @@ struct rtl8187_tx_hdr {
struct rtl8187_priv {
/* common between rtl818x drivers */
struct rtl818x_csr *map;
- void (*rf_init)(struct ieee80211_hw *);
+ const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif;
int mode;

diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 13399de..0d71716 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -394,7 +394,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
msleep(100);

- priv->rf_init(dev);
+ priv->rf->init(dev);

rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1;
@@ -407,24 +407,6 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
return 0;
}

-static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
-{
- u32 reg;
- struct rtl8187_priv *priv = dev->priv;
-
- reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
- /* Enable TX loopback on MAC level to avoid TX during channel
- * changes, as this has be seen to causes problems and the
- * card will stop work until next reset
- */
- rtl818x_iowrite32(priv, &priv->map->TX_CONF,
- reg | RTL818X_TX_CONF_LOOPBACK_MAC);
- msleep(10);
- rtl8225_rf_set_channel(dev, channel);
- msleep(10);
- rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
-}
-
static int rtl8187_start(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
@@ -493,7 +475,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
reg &= ~RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);

- rtl8225_rf_stop(dev);
+ priv->rf->stop(dev);

rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
@@ -544,7 +526,19 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
- rtl8187_set_channel(dev, conf->channel);
+ u32 reg;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ /* Enable TX loopback on MAC level to avoid TX during channel
+ * changes, as this has be seen to causes problems and the
+ * card will stop work until next reset
+ */
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+ msleep(10);
+ priv->rf->set_chan(dev, conf);
+ msleep(10);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);

rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);

@@ -762,14 +756,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);

- rtl8225_write(dev, 0, 0x1B7);
-
- if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
- priv->rf_init = rtl8225_rf_init;
- else
- priv->rf_init = rtl8225z2_rf_init;
-
- rtl8225_write(dev, 0, 0x0B7);
+ priv->rf = rtl8187_detect_rf(dev);

err = ieee80211_register_hw(dev);
if (err) {
@@ -779,8 +766,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,

printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
- priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
- "rtl8225" : "rtl8225z2");
+ priv->asic_rev, priv->rf->name);

return 0;

diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index eade81f..c04ad34 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -101,7 +101,7 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
msleep(2);
}

-void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;

@@ -111,7 +111,7 @@ void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
rtl8225_write_bitbang(dev, addr, data);
}

-u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg82, reg84, out;
@@ -325,7 +325,7 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
msleep(1);
}

-void rtl8225_rf_init(struct ieee80211_hw *dev)
+static void rtl8225_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
@@ -567,7 +567,7 @@ static const u8 rtl8225z2_gain_bg[] = {
0x63, 0x15, 0xc5 /* -66dBm */
};

-void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
@@ -715,7 +715,7 @@ void rtl8225z2_rf_init(struct ieee80211_hw *dev)
rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
}

-void rtl8225_rf_stop(struct ieee80211_hw *dev)
+static void rtl8225_rf_stop(struct ieee80211_hw *dev)
{
u8 reg;
struct rtl8187_priv *priv = dev->priv;
@@ -731,15 +731,47 @@ void rtl8225_rf_stop(struct ieee80211_hw *dev)
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
}

-void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;

- if (priv->rf_init == rtl8225_rf_init)
- rtl8225_rf_set_tx_power(dev, channel);
+ if (priv->rf->init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, conf->channel);
else
- rtl8225z2_rf_set_tx_power(dev, channel);
+ rtl8225z2_rf_set_tx_power(dev, conf->channel);

- rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+ rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
msleep(10);
}
+
+static const struct rtl818x_rf_ops rtl8225_ops = {
+ .name = "rtl8225",
+ .init = rtl8225_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+static const struct rtl818x_rf_ops rtl8225z2_ops = {
+ .name = "rtl8225z2",
+ .init = rtl8225z2_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
+{
+ u16 reg8, reg9;
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ reg8 = rtl8225_read(dev, 8);
+ reg9 = rtl8225_read(dev, 9);
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ if (reg8 != 0x588 || reg9 != 0x700)
+ return &rtl8225_ops;
+
+ return &rtl8225z2_ops;
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
index 798ba4a..d39ed02 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.h
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -20,14 +20,7 @@
#define RTL8225_ANAPARAM_OFF 0xa00beb59
#define RTL8225_ANAPARAM2_OFF 0x840dec11

-void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
-u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
-
-void rtl8225_rf_init(struct ieee80211_hw *);
-void rtl8225z2_rf_init(struct ieee80211_hw *);
-void rtl8225_rf_stop(struct ieee80211_hw *);
-void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
-
+const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *);

static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
u8 addr, u32 data)
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
index 1322f6a..1e7d6f8 100644
--- a/drivers/net/wireless/rtl818x.h
+++ b/drivers/net/wireless/rtl818x.h
@@ -168,6 +168,13 @@ struct rtl818x_csr {
u8 TALLY_SEL;
} __attribute__((packed));

+struct rtl818x_rf_ops {
+ char *name;
+ void (*init)(struct ieee80211_hw *);
+ void (*stop)(struct ieee80211_hw *);
+ void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+};
+
static const struct ieee80211_rate rtl818x_rates[] = {
{ .rate = 10,
.val = 0,