summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-07-15 18:05:24 +0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-15 18:05:24 +0400
commit95a943c162d74b20d869917bdf5df11293c35b63 (patch)
treec69d5cb97a4d97b6062a276ecdfa8582535193af /drivers/net/wireless/b43
parentecae42d37045ec71831d0e0e493e00b0e0732edd (diff)
parent95acac61ba66c4abd40e038dae8c1ed2e176c7b1 (diff)
downloadlinux-95a943c162d74b20d869917bdf5df11293c35b63.tar.xz
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: net/bluetooth/l2cap_core.c
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/Kconfig14
-rw-r--r--drivers/net/wireless/b43/Makefile1
-rw-r--r--drivers/net/wireless/b43/b43.h1
-rw-r--r--drivers/net/wireless/b43/bus.c129
-rw-r--r--drivers/net/wireless/b43/bus.h8
-rw-r--r--drivers/net/wireless/b43/dma.c9
-rw-r--r--drivers/net/wireless/b43/main.c361
-rw-r--r--drivers/net/wireless/b43/phy_common.c6
-rw-r--r--drivers/net/wireless/b43/phy_common.h3
-rw-r--r--drivers/net/wireless/b43/phy_ht.c12
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c52
-rw-r--r--drivers/net/wireless/b43/phy_lcn.h14
-rw-r--r--drivers/net/wireless/b43/phy_n.c62
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.c34
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.h6
-rw-r--r--drivers/net/wireless/b43/xmit.c3
16 files changed, 622 insertions, 93 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index d5add69aac8f..d2293dcc117f 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -90,6 +90,12 @@ config B43_SDIO
#Data transfers to the device via PIO. We want it as a fallback even
# if we can do DMA.
+config B43_BCMA_PIO
+ bool
+ depends on B43_BCMA
+ select BCMA_BLOCKIO
+ default y
+
config B43_PIO
bool
depends on B43
@@ -125,6 +131,14 @@ config B43_PHY_HT
Say N, this is BROKEN and crashes driver.
+config B43_PHY_LCN
+ bool "Support for LCN-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the LCN-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 1b25604be547..4648bbf76abc 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -13,6 +13,7 @@ b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
b43-$(CONFIG_B43_PHY_HT) += phy_ht.o
b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o
b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
+b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 666515e348b5..08a28270bbb3 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -726,7 +726,6 @@ enum {
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
- struct ssb_device *sdev; /* TODO: remove when b43_bus_dev is ready */
struct b43_bus_dev *dev;
struct b43_wl *wl;
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
index 4200713eb597..a5e61a9fb539 100644
--- a/drivers/net/wireless/b43/bus.c
+++ b/drivers/net/wireless/b43/bus.c
@@ -23,6 +23,106 @@
#include "b43.h"
#include "bus.h"
+/* BCMA */
+#ifdef CONFIG_B43_BCMA
+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+ return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
+}
+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
+ bool dynamic_pctl)
+{
+ return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
+}
+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
+{
+ return bcma_core_is_enabled(dev->bdev);
+}
+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_enable(dev->bdev, core_specific_flags);
+}
+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_disable(dev->bdev, core_specific_flags);
+}
+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read16(dev->bdev, offset);
+}
+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read32(dev->bdev, offset);
+}
+static
+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+ bcma_write16(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+ bcma_write32(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
+{
+ struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->bus_type = B43_BUS_BCMA;
+ dev->bdev = core;
+
+ dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
+ dev->bus_powerup = b43_bus_bcma_bus_powerup;
+ dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
+ dev->device_enable = b43_bus_bcma_device_enable;
+ dev->device_disable = b43_bus_bcma_device_disable;
+
+ dev->read16 = b43_bus_bcma_read16;
+ dev->read32 = b43_bus_bcma_read32;
+ dev->write16 = b43_bus_bcma_write16;
+ dev->write32 = b43_bus_bcma_write32;
+ dev->block_read = b43_bus_bcma_block_read;
+ dev->block_write = b43_bus_bcma_block_write;
+
+ dev->dev = &core->dev;
+ dev->dma_dev = core->dma_dev;
+ dev->irq = core->irq;
+
+ /*
+ dev->board_vendor = core->bus->boardinfo.vendor;
+ dev->board_type = core->bus->boardinfo.type;
+ dev->board_rev = core->bus->boardinfo.rev;
+ */
+
+ dev->chip_id = core->bus->chipinfo.id;
+ dev->chip_rev = core->bus->chipinfo.rev;
+ dev->chip_pkg = core->bus->chipinfo.pkg;
+
+ dev->bus_sprom = &core->bus->sprom;
+
+ dev->core_id = core->id.id;
+ dev->core_rev = core->id.rev;
+
+ return dev;
+}
+#endif /* CONFIG_B43_BCMA */
/* SSB */
#ifdef CONFIG_B43_SSB
@@ -125,3 +225,32 @@ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
return dev;
}
#endif /* CONFIG_B43_SSB */
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev)
+{
+ switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ return bcma_get_drvdata(dev->bdev);
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ return ssb_get_drvdata(dev->sdev);
+#endif
+ }
+ return NULL;
+}
+
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev)
+{
+ switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_set_drvdata(dev->bdev, wldev);
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_set_drvdata(dev->sdev, wldev);
+#endif
+ }
+}
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h
index 79a5ab4270c3..184c95659279 100644
--- a/drivers/net/wireless/b43/bus.h
+++ b/drivers/net/wireless/b43/bus.h
@@ -2,12 +2,16 @@
#define B43_BUS_H_
enum b43_bus_type {
+#ifdef CONFIG_B43_BCMA
+ B43_BUS_BCMA,
+#endif
B43_BUS_SSB,
};
struct b43_bus_dev {
enum b43_bus_type bus_type;
union {
+ struct bcma_device *bdev;
struct ssb_device *sdev;
};
@@ -57,6 +61,10 @@ static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
}
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+void *b43_bus_get_wldev(struct b43_bus_dev *dev);
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data);
+
#endif /* B43_BUS_H_ */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 7a09a467339c..ce572aebeffd 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1055,7 +1055,14 @@ int b43_dma_init(struct b43_wldev *dev)
err = b43_dma_set_mask(dev, dmamask);
if (err)
return err;
- dma->translation = ssb_dma_translation(dev->sdev);
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ dma->translation = ssb_dma_translation(dev->dev->sdev);
+ break;
+#endif
+ }
err = -ENOMEM;
/* setup TX DMA channels. */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index e9a01e3eede7..092dd9318869 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1155,6 +1155,21 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
}
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+ u32 flags = 0;
+
+ if (gmode)
+ flags = B43_BCMA_IOCTL_GMODE;
+ flags |= B43_BCMA_IOCTL_PHY_CLKEN;
+ flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
+ b43_device_enable(dev, flags);
+
+ /* TODO: reset PHY */
+}
+#endif
+
static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
struct ssb_device *sdev = dev->dev->sdev;
@@ -1187,7 +1202,18 @@ void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
u32 macctl;
- b43_ssb_wireless_core_reset(dev, gmode);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43_bcma_wireless_core_reset(dev, gmode);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_ssb_wireless_core_reset(dev, gmode);
+ break;
+#endif
+ }
/* Turn Analog ON, but only if we already know the PHY-type.
* This protects against very early setup where we don't know the
@@ -1938,7 +1964,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
return IRQ_NONE;
reason &= dev->irq_mask;
if (!reason)
- return IRQ_HANDLED;
+ return IRQ_NONE;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
& 0x0001DC00;
@@ -2133,21 +2159,43 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
u32 tmshigh;
int err;
+ /* Files for HT and LCN were found by trying one by one */
+
/* Get microcode */
- if ((rev >= 5) && (rev <= 10))
+ if ((rev >= 5) && (rev <= 10)) {
filename = "ucode5";
- else if ((rev >= 11) && (rev <= 12))
+ } else if ((rev >= 11) && (rev <= 12)) {
filename = "ucode11";
- else if (rev == 13)
+ } else if (rev == 13) {
filename = "ucode13";
- else if (rev == 14)
+ } else if (rev == 14) {
filename = "ucode14";
- else if (rev == 15)
+ } else if (rev == 15) {
filename = "ucode15";
- else if ((rev >= 16) && (rev <= 20))
- filename = "ucode16_mimo";
- else
- goto err_no_ucode;
+ } else {
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_N:
+ if (rev >= 16)
+ filename = "ucode16_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ucode29_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "ucode24_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ default:
+ goto err_no_ucode;
+ }
+ }
err = b43_do_request_fw(ctx, filename, &fw->ucode);
if (err)
goto err_load;
@@ -2206,6 +2254,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0initvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0initvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2253,6 +2313,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0bsinitvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0bsinitvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
@@ -2624,11 +2696,24 @@ static int b43_gpio_init(struct b43_wldev *dev)
if (dev->dev->core_rev >= 2)
mask |= 0x0010; /* FIXME: This is redundant. */
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL,
- (ssb_read32(gpiodev, B43_GPIO_CONTROL)
- & mask) | set);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_GPIOCTL) & mask) | set);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL,
+ (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+ & mask) | set);
+ break;
+#endif
+ }
return 0;
}
@@ -2638,9 +2723,21 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
{
struct ssb_device *gpiodev;
- gpiodev = b43_ssb_gpio_dev(dev);
- if (gpiodev)
- ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+ 0);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ gpiodev = b43_ssb_gpio_dev(dev);
+ if (gpiodev)
+ ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+ break;
+#endif
+ }
}
/* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2712,12 +2809,30 @@ out:
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{
- u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (on)
- tmslow |= B43_TMSLOW_MACPHYCLKEN;
- else
- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+ u32 tmp;
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL);
+ if (on)
+ tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
+ else
+ tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
+ bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (on)
+ tmp |= B43_TMSLOW_MACPHYCLKEN;
+ else
+ tmp &= ~B43_TMSLOW_MACPHYCLKEN;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
}
static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2956,8 +3071,20 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_mac_phy_clock_set(dev, true);
- b43_write16(dev, B43_MMIO_POWERUP_DELAY,
- dev->sdev->bus->chipco.fast_pwrup_delay);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* FIXME: 0xE74 is quite common, but should be read from CC */
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+ dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+ break;
+#endif
+ }
err = 0;
b43dbg(dev->wl, "Chip initialized\n");
@@ -3473,21 +3600,33 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
- struct ssb_device *sdev = dev->sdev;
- u32 tmslow;
+ u32 tmp;
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43_TMSLOW_GMODE;
- tmslow |= B43_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ b43err(dev->wl,
+ "Putting PHY into reset not supported on BCMA\n");
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~B43_TMSLOW_GMODE;
+ tmp |= B43_TMSLOW_PHYRESET;
+ tmp |= SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
+
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~SSB_TMSLOW_FGC;
+ tmp |= B43_TMSLOW_PHYRESET;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ msleep(1);
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
+ break;
+#endif
+ }
}
static const char *band_to_string(enum ieee80211_band band)
@@ -4104,6 +4243,12 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
#endif
+#ifdef CONFIG_B43_PHY_LCN
+ case B43_PHYTYPE_LCN:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
default:
unsupported = 1;
}
@@ -4117,22 +4262,42 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type, phy_type, phy_rev);
/* Get RADIO versioning */
- if (dev->dev->chip_id == 0x4317) {
- if (dev->dev->chip_rev == 0)
- tmp = 0x3205017F;
- else if (dev->dev->chip_rev == 1)
- tmp = 0x4205017F;
- else
- tmp = 0x5205017F;
+ if (dev->dev->core_rev >= 24) {
+ u16 radio24[3];
+
+ for (tmp = 0; tmp < 3; tmp++) {
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+ radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+
+ /* Broadcom uses "id" for our "ver" and has separated "ver" */
+ /* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+ radio_manuf = 0x17F;
+ radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_rev = (radio24[0] & 0xF);
} else {
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
- }
- radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
- radio_rev = (tmp & 0xF0000000) >> 28;
+ if (dev->dev->chip_id == 0x4317) {
+ if (dev->dev->chip_rev == 0)
+ tmp = 0x3205017F;
+ else if (dev->dev->chip_rev == 1)
+ tmp = 0x4205017F;
+ else
+ tmp = 0x5205017F;
+ } else {
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+ << 16;
+ }
+ radio_manuf = (tmp & 0x00000FFF);
+ radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_rev = (tmp & 0xF0000000) >> 28;
+ }
+
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
@@ -4164,6 +4329,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
if (radio_ver != 0x2059)
unsupported = 1;
break;
+ case B43_PHYTYPE_LCN:
+ if (radio_ver != 0x2064)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4347,7 +4516,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
/* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
int err;
@@ -4366,7 +4534,20 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
phy->ops->prepare_structs(dev);
/* Enable IRQ routing to this device. */
- ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+ dev->dev->bdev, true);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
+ dev->dev->sdev);
+ break;
+#endif
+ }
b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev);
@@ -4397,8 +4578,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
#ifdef CONFIG_SSB_DRIVER_PCICORE
- if ((bus->bustype == SSB_BUSTYPE_PCI) &&
- (bus->pcicore.dev->id.revision <= 10))
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
#endif
hf &= ~B43_HF_SKCFPUP;
@@ -4764,8 +4946,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
static int b43_wireless_core_attach(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
- struct ssb_bus *bus = dev->sdev->bus;
- struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+ struct pci_dev *pdev = NULL;
int err;
bool have_2ghz_phy = 0, have_5ghz_phy = 0;
@@ -4776,20 +4957,38 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
* that in core_init(), too.
*/
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+ pdev = dev->dev->sdev->bus->host_pci;
+#endif
+
err = b43_bus_powerup(dev, 0);
if (err) {
b43err(wl, "Bus powerup failed\n");
goto out;
}
- /* Get the PHY type. */
- if (dev->dev->core_rev >= 5) {
- u32 tmshigh;
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
- have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
- } else
- B43_WARN_ON(1);
+ /* Get the PHY type. */
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* FIXME */
+ have_2ghz_phy = 1;
+ have_5ghz_phy = 0;
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ if (dev->dev->core_rev >= 5) {
+ u32 tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+ have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
+ have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
+ } else
+ B43_WARN_ON(1);
+ break;
+#endif
+ }
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = 1;
@@ -4815,6 +5014,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
#endif
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
have_2ghz_phy = 1;
break;
default:
@@ -4877,13 +5078,13 @@ static void b43_one_core_detach(struct b43_bus_dev *dev)
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
- wldev = ssb_get_drvdata(dev->sdev);
+ wldev = b43_bus_get_wldev(dev);
wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
wl->nr_devs--;
- ssb_set_drvdata(dev->sdev, NULL);
+ b43_bus_set_wldev(dev, NULL);
kfree(wldev);
}
@@ -4898,7 +5099,6 @@ static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
wldev->use_pio = b43_modparam_pio;
wldev->dev = dev;
- wldev->sdev = dev->sdev; /* TODO: Remove when not needed */
wldev->wl = wl;
b43_set_status(wldev, B43_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4910,7 +5110,7 @@ static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
list_add(&wldev->list, &wl->devlist);
wl->nr_devs++;
- ssb_set_drvdata(dev->sdev, wldev);
+ b43_bus_set_wldev(dev, wldev);
b43_debugfs_add_device(wldev);
out:
@@ -4959,9 +5159,9 @@ static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
ieee80211_free_hw(hw);
}
-static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
- struct ssb_sprom *sprom = &dev->bus->sprom;
+ struct ssb_sprom *sprom = dev->bus_sprom;
struct ieee80211_hw *hw;
struct b43_wl *wl;
@@ -5003,14 +5203,21 @@ static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
skb_queue_head_init(&wl->tx_queue);
b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
- dev->bus->chip_id, dev->id.revision);
+ dev->chip_id, dev->core_rev);
return wl;
}
#ifdef CONFIG_B43_BCMA
static int b43_bcma_probe(struct bcma_device *core)
{
+ struct b43_bus_dev *dev;
+
+ dev = b43_bus_dev_bcma_init(core);
+ if (!dev)
+ return -ENODEV;
+
b43err(NULL, "BCMA is not supported yet!");
+ kfree(dev);
return -EOPNOTSUPP;
}
@@ -5045,7 +5252,7 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
/* Probing the first core. Must setup common struct b43_wl */
first = 1;
b43_sprom_fixup(sdev->bus);
- wl = b43_wireless_init(sdev);
+ wl = b43_wireless_init(dev);
if (IS_ERR(wl)) {
err = PTR_ERR(wl);
goto out;
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 9705950f059a..101957512bcc 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -32,6 +32,7 @@
#include "phy_n.h"
#include "phy_lp.h"
#include "phy_ht.h"
+#include "phy_lcn.h"
#include "b43.h"
#include "main.h"
@@ -65,6 +66,11 @@ int b43_phy_allocate(struct b43_wldev *dev)
phy->ops = &b43_phyops_ht;
#endif
break;
+ case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+ phy->ops = &b43_phyops_lcn;
+#endif
+ break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 47dcb800a3c3..aa77ba612a92 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -195,6 +195,7 @@ struct b43_phy_g;
struct b43_phy_n;
struct b43_phy_lp;
struct b43_phy_ht;
+struct b43_phy_lcn;
struct b43_phy {
/* Hardware operation callbacks. */
@@ -219,6 +220,8 @@ struct b43_phy {
struct b43_phy_lp *lp;
/* HT-PHY specific information */
struct b43_phy_ht *ht;
+ /* LCN-PHY specific information */
+ struct b43_phy_lcn *lcn;
};
/* Band support flags. */
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index 30b19c61037d..29821036badf 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -373,6 +373,16 @@ static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
}
+static enum b43_txpwr_result
+b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
/**************************************************
* PHY ops struct.
**************************************************/
@@ -391,8 +401,6 @@ const struct b43_phy_operations b43_phyops_ht = {
.switch_analog = b43_phy_ht_op_switch_analog,
.switch_channel = b43_phy_ht_op_switch_channel,
.get_default_chan = b43_phy_ht_op_get_default_chan,
- /*
.recalc_txpower = b43_phy_ht_op_recalc_txpower,
.adjust_txpower = b43_phy_ht_op_adjust_txpower,
- */
};
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
new file mode 100644
index 000000000000..9f7dbbd5ced6
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -0,0 +1,52 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n LCN-PHY support
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_lcn.h"
+#include "tables_phy_lcn.h"
+#include "main.h"
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_lcn = {
+ /*
+ .allocate = b43_phy_lcn_op_allocate,
+ .free = b43_phy_lcn_op_free,
+ .prepare_structs = b43_phy_lcn_op_prepare_structs,
+ .init = b43_phy_lcn_op_init,
+ .phy_read = b43_phy_lcn_op_read,
+ .phy_write = b43_phy_lcn_op_write,
+ .phy_maskset = b43_phy_lcn_op_maskset,
+ .radio_read = b43_phy_lcn_op_radio_read,
+ .radio_write = b43_phy_lcn_op_radio_write,
+ .software_rfkill = b43_phy_lcn_op_software_rfkill,
+ .switch_analog = b43_phy_lcn_op_switch_analog,
+ .switch_channel = b43_phy_lcn_op_switch_channel,
+ .get_default_chan = b43_phy_lcn_op_get_default_chan,
+ .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
+ .adjust_txpower = b43_phy_lcn_op_adjust_txpower,
+ */
+};
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
new file mode 100644
index 000000000000..c046c2a6cab4
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -0,0 +1,14 @@
+#ifndef B43_PHY_LCN_H_
+#define B43_PHY_LCN_H_
+
+#include "phy_common.h"
+
+
+struct b43_phy_lcn {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lcn;
+
+#endif /* B43_PHY_LCN_H_ */ \ No newline at end of file
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index e7dfdac9e4d7..95c28f584ed9 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -603,17 +603,33 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
{
- u32 tmslow;
+ u32 tmp;
if (dev->phy.type != B43_PHYTYPE_N)
return;
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL);
+ if (force)
+ tmp |= BCMA_IOCTL_FGC;
+ else
+ tmp &= ~BCMA_IOCTL_FGC;
+ bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (force)
+ tmp |= SSB_TMSLOW_FGC;
+ else
+ tmp &= ~SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
@@ -958,8 +974,21 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
- ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
- 0xFC00);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+ 0xFC00, 0xFC00);
+ break;
+#endif
+ }
+
b43_write32(dev, B43_MMIO_MACCTL,
b43_read32(dev, B43_MMIO_MACCTL) &
~B43_MACCTL_GPOUTSMSK);
@@ -3600,7 +3629,20 @@ int b43_phy_initn(struct b43_wldev *dev)
if ((dev->phy.rev >= 3) &&
(sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
- chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_CHIPCTL, 0x40);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ chipco_set32(&dev->dev->sdev->bus->chipco,
+ SSB_CHIPCO_CHIPCTL, 0x40);
+ break;
+#endif
+ }
}
nphy->deaf_count = 0;
b43_nphy_tables_init(dev);
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c
new file mode 100644
index 000000000000..40c1d0915dd3
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -0,0 +1,34 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n LCN-PHY data tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_lcn.h"
+#include "phy_common.h"
+#include "phy_lcn.h"
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+}
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h
new file mode 100644
index 000000000000..5e31b15b81ec
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -0,0 +1,6 @@
+#ifndef B43_TABLES_PHY_LCN_H_
+#define B43_TABLES_PHY_LCN_H_
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 488b898418a3..82bcf7595139 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* we give the phase1key and iv16 here, the key is stored in
* shm. With that the hardware can do phase 2 and encryption.
*/
- ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
- IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+ ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
for (i = 0; i < 5; i++) {
txhdr->iv[i * 2 + 0] = phase1key[i];