Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6532111 authored by Michael Wu's avatar Michael Wu Committed by David S. Miller
Browse files

Add rtl8180 wireless driver



This patch adds a mac80211 based wireless driver for the rtl8180 and
rtl8185 PCI wireless cards.  Also included are some rtl8187 changes
required due to the relationship between that driver and this one.

Michael Wu is primarily responsible for the initial driver and rtl8185
support.  Andreas Merello provided the additional rtl8180 support.

Thanks to Jukka Ruohonen for the donating a rtl8185 card! It was very
helpful for the rtl8225z2 code.

The Signed-off-by information below is collected from the individual
patches submitted to wireless-2.6 before merging this driver upstream.

Signed-off-by: default avatarAndrea Merello <andreamrl@tiscali.it>
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarPavel Roskin <proski@gnu.org>
Signed-off-by: default avatarMichael Wu <flamingice@sourmilk.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent fa1c114f
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -545,6 +545,62 @@ config USB_ZD1201
	  To compile this driver as a module, choose M here: the
	  module will be called zd1201.

config RTL8180
	tristate "Realtek 8180/8185 PCI support"
	depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
	select EEPROM_93CX6
	---help---
	  This is a driver for RTL8180 and RTL8185 based cards.
	  These are PCI based chips found in cards such as:

	  (RTL8185 802.11g)
	  A-Link WL54PC

	  (RTL8180 802.11b)
	  Belkin F5D6020 v3
	  Belkin F5D6020 v3
	  Dlink DWL-610
	  Dlink DWL-510
	  Netgear MA521
	  Level-One WPC-0101
	  Acer Aspire 1357 LMi
	  VCTnet PC-11B1
	  Ovislink AirLive WL-1120PCM
	  Mentor WL-PCI
	  Linksys WPC11 v4
	  TrendNET TEW-288PI
	  D-Link DWL-520 Rev D
	  Repotec RP-WP7126
	  TP-Link TL-WN250/251
	  Zonet ZEW1000
	  Longshine LCS-8031-R
	  HomeLine HLW-PCC200
	  GigaFast WF721-AEX
	  Planet WL-3553
	  Encore ENLWI-PCI1-NT
	  TrendNET TEW-266PC
	  Gigabyte GN-WLMR101
	  Siemens-fujitsu Amilo D1840W
	  Edimax EW-7126
	  PheeNet WL-11PCIR
	  Tonze PC-2100T
	  Planet WL-8303
	  Dlink DWL-650 v M1
	  Edimax EW-7106
	  Q-Tec 770WC
	  Topcom Skyr@cer 4011b
	  Roper FreeLan 802.11b (edition 2004)
	  Wistron Neweb Corp CB-200B
	  Pentagram HorNET
	  QTec 775WC
	  TwinMOS Booming B Series
	  Micronet SP906BB
	  Sweex LC700010
	  Surecom EP-9428
	  Safecom SWLCR-1100

	  Thanks to Realtek for their support!

config RTL8187
	tristate "Realtek 8187 USB support"
	depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+3 −0
Original line number Diff line number Diff line
@@ -47,7 +47,10 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
obj-$(CONFIG_LIBERTAS)		+= libertas/

rtl8180-objs		:= rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o

obj-$(CONFIG_RTL8180)	+= rtl8180.o
obj-$(CONFIG_RTL8187)	+= rtl8187.o

obj-$(CONFIG_ADM8211)	+= adm8211.o
+151 −0
Original line number Diff line number Diff line
#ifndef RTL8180_H
#define RTL8180_H

#include "rtl818x.h"

#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD

#define RF_PARAM_ANALOGPHY	(1 << 0)
#define RF_PARAM_ANTBDEFAULT	(1 << 1)
#define RF_PARAM_CARRIERSENSE1	(1 << 2)
#define RF_PARAM_CARRIERSENSE2	(1 << 3)

#define BB_ANTATTEN_CHAN14	0x0C
#define BB_ANTENNA_B 		0x40

#define BB_HOST_BANG 		(1 << 30)
#define BB_HOST_BANG_EN 	(1 << 2)
#define BB_HOST_BANG_CLK 	(1 << 1)
#define BB_HOST_BANG_DATA	1

#define ANAPARAM_TXDACOFF_SHIFT	27
#define ANAPARAM_PWR0_SHIFT	28
#define ANAPARAM_PWR0_MASK 	(0x07 << ANAPARAM_PWR0_SHIFT)
#define ANAPARAM_PWR1_SHIFT	20
#define ANAPARAM_PWR1_MASK	(0x7F << ANAPARAM_PWR1_SHIFT)

enum rtl8180_tx_desc_flags {
	RTL8180_TX_DESC_FLAG_NO_ENC	= (1 << 15),
	RTL8180_TX_DESC_FLAG_TX_OK	= (1 << 15),
	RTL8180_TX_DESC_FLAG_SPLCP	= (1 << 16),
	RTL8180_TX_DESC_FLAG_RX_UNDER	= (1 << 16),
	RTL8180_TX_DESC_FLAG_MOREFRAG	= (1 << 17),
	RTL8180_TX_DESC_FLAG_CTS	= (1 << 18),
	RTL8180_TX_DESC_FLAG_RTS	= (1 << 23),
	RTL8180_TX_DESC_FLAG_LS		= (1 << 28),
	RTL8180_TX_DESC_FLAG_FS		= (1 << 29),
	RTL8180_TX_DESC_FLAG_DMA	= (1 << 30),
	RTL8180_TX_DESC_FLAG_OWN	= (1 << 31)
};

struct rtl8180_tx_desc {
	__le32 flags;
	__le16 rts_duration;
	__le16 plcp_len;
	__le32 tx_buf;
	__le32 frame_len;
	__le32 next_tx_desc;
	u8 cw;
	u8 retry_limit;
	u8 agc;
	u8 flags2;
	u32 reserved[2];
} __attribute__ ((packed));

enum rtl8180_rx_desc_flags {
	RTL8180_RX_DESC_FLAG_ICV_ERR	= (1 << 12),
	RTL8180_RX_DESC_FLAG_CRC32_ERR	= (1 << 13),
	RTL8180_RX_DESC_FLAG_PM		= (1 << 14),
	RTL8180_RX_DESC_FLAG_RX_ERR	= (1 << 15),
	RTL8180_RX_DESC_FLAG_BCAST	= (1 << 16),
	RTL8180_RX_DESC_FLAG_PAM	= (1 << 17),
	RTL8180_RX_DESC_FLAG_MCAST	= (1 << 18),
	RTL8180_RX_DESC_FLAG_SPLCP	= (1 << 25),
	RTL8180_RX_DESC_FLAG_FOF	= (1 << 26),
	RTL8180_RX_DESC_FLAG_DMA_FAIL	= (1 << 27),
	RTL8180_RX_DESC_FLAG_LS		= (1 << 28),
	RTL8180_RX_DESC_FLAG_FS		= (1 << 29),
	RTL8180_RX_DESC_FLAG_EOR	= (1 << 30),
	RTL8180_RX_DESC_FLAG_OWN	= (1 << 31)
};

struct rtl8180_rx_desc {
	__le32 flags;
	__le32 flags2;
	union {
		__le32 rx_buf;
		__le64 tsft;
	};
} __attribute__ ((packed));

struct rtl8180_tx_ring {
	struct rtl8180_tx_desc *desc;
	dma_addr_t dma;
	unsigned int idx;
	unsigned int entries;
	struct sk_buff_head queue;
};

struct rtl8180_priv {
	/* common between rtl818x drivers */
	struct rtl818x_csr __iomem *map;
	const struct rtl818x_rf_ops *rf;
	int mode;
	int if_id;

	/* rtl8180 driver specific */
	spinlock_t lock;
	struct rtl8180_rx_desc *rx_ring;
	dma_addr_t rx_ring_dma;
	unsigned int rx_idx;
	struct sk_buff *rx_buf[32];
	struct rtl8180_tx_ring tx_ring[4];
	struct ieee80211_channel channels[14];
	struct ieee80211_rate rates[12];
	struct ieee80211_hw_mode modes[2];
	struct pci_dev *pdev;
	u32 rx_conf;

	int r8185;
	u32 anaparam;
	u16 rfparam;
	u8 csthreshold;
};

void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam);

static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr)
{
	return ioread8(addr);
}

static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr)
{
	return ioread16(addr);
}

static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr)
{
	return ioread32(addr);
}

static inline void rtl818x_iowrite8(struct rtl8180_priv *priv,
				    u8 __iomem *addr, u8 val)
{
	iowrite8(val, addr);
}

static inline void rtl818x_iowrite16(struct rtl8180_priv *priv,
				     __le16 __iomem *addr, u16 val)
{
	iowrite16(val, addr);
}

static inline void rtl818x_iowrite32(struct rtl8180_priv *priv,
				     __le32 __iomem *addr, u32 val)
{
	iowrite32(val, addr);
}

#endif /* RTL8180_H */
+1048 −0

File added.

Preview size limit exceeded, changes collapsed.

+179 −0
Original line number Diff line number Diff line

/*
 * Radio tuning for GCT GRF5101 on RTL8180
 *
 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
 *
 * 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!
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <net/mac80211.h>

#include "rtl8180.h"
#include "rtl8180_grf5101.h"

static const int grf5101_encode[] = {
	0x0, 0x8, 0x4, 0xC,
	0x2, 0xA, 0x6, 0xE,
	0x1, 0x9, 0x5, 0xD,
	0x3, 0xB, 0x7, 0xF
};

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) & 0xF];
	phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4;
	phy_config |= grf5101_encode[data & 0xF] << 8;
	phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12;
	phy_config |= (addr & 1) << 16;
	phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24;

	/* MAC will bang bits to the chip */
	phy_config |= 0x90000000;

	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, 0x10, ant);
}

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;
	u32 chan = conf->channel - 1;

	/* set TX power */
	write_grf5101(dev, 0x15, 0x0);
	write_grf5101(dev, 0x06, txpw);
	write_grf5101(dev, 0x15, 0x10);
	write_grf5101(dev, 0x15, 0x0);

	/* set frequency */
	write_grf5101(dev, 0x07, 0x0);
	write_grf5101(dev, 0x0B, chan);
	write_grf5101(dev, 0x07, 0x1000);

	grf5101_write_phy_antenna(dev, chan);
}

static void grf5101_rf_stop(struct ieee80211_hw *dev)
{
	struct rtl8180_priv *priv = dev->priv;
	u32 anaparam;

	anaparam = priv->anaparam;
	anaparam &= 0x000fffff;
	anaparam |= 0x3f900000;
	rtl8180_set_anaparam(priv, anaparam);

	write_grf5101(dev, 0x07, 0x0);
	write_grf5101(dev, 0x1f, 0x45);
	write_grf5101(dev, 0x1f, 0x5);
	write_grf5101(dev, 0x00, 0x8e4);
}

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

	rtl8180_set_anaparam(priv, priv->anaparam);

	write_grf5101(dev, 0x1f, 0x0);
	write_grf5101(dev, 0x1f, 0x0);
	write_grf5101(dev, 0x1f, 0x40);
	write_grf5101(dev, 0x1f, 0x60);
	write_grf5101(dev, 0x1f, 0x61);
	write_grf5101(dev, 0x1f, 0x61);
	write_grf5101(dev, 0x00, 0xae4);
	write_grf5101(dev, 0x1f, 0x1);
	write_grf5101(dev, 0x1f, 0x41);
	write_grf5101(dev, 0x1f, 0x61);

	write_grf5101(dev, 0x01, 0x1a23);
	write_grf5101(dev, 0x02, 0x4971);
	write_grf5101(dev, 0x03, 0x41de);
	write_grf5101(dev, 0x04, 0x2d80);
	write_grf5101(dev, 0x05, 0x68ff);	/* 0x61ff original value */
	write_grf5101(dev, 0x06, 0x0);
	write_grf5101(dev, 0x07, 0x0);
	write_grf5101(dev, 0x08, 0x7533);
	write_grf5101(dev, 0x09, 0xc401);
	write_grf5101(dev, 0x0a, 0x0);
	write_grf5101(dev, 0x0c, 0x1c7);
	write_grf5101(dev, 0x0d, 0x29d3);
	write_grf5101(dev, 0x0e, 0x2e8);
	write_grf5101(dev, 0x10, 0x192);
	write_grf5101(dev, 0x11, 0x248);
	write_grf5101(dev, 0x12, 0x0);
	write_grf5101(dev, 0x13, 0x20c4);
	write_grf5101(dev, 0x14, 0xf4fc);
	write_grf5101(dev, 0x15, 0x0);
	write_grf5101(dev, 0x16, 0x1500);

	write_grf5101(dev, 0x07, 0x1000);

	/* baseband configuration */
	rtl8180_write_phy(dev, 0, 0xa8);
	rtl8180_write_phy(dev, 3, 0x0);
	rtl8180_write_phy(dev, 4, 0xc0);
	rtl8180_write_phy(dev, 5, 0x90);
	rtl8180_write_phy(dev, 6, 0x1e);
	rtl8180_write_phy(dev, 7, 0x64);

	grf5101_write_phy_antenna(dev, 1);

	rtl8180_write_phy(dev, 0x11, 0x88);

	if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
	    RTL818X_CONFIG2_ANTENNA_DIV)
		rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */
	else
		rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */

	rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold);

	rtl8180_write_phy(dev, 0x19, 0x0);
	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
};
Loading