b43: move under broadcom vendor directory

Part of reorganising wireless drivers directory and Kconfig.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Kalle Valo
2015-11-17 19:49:23 +02:00
parent 30fe0f9b8c
commit 58619b14d1
68 changed files with 20 additions and 3 deletions

View File

@@ -0,0 +1,187 @@
config B43
tristate "Broadcom 43xx wireless support (mac80211 stack)"
depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA
select BCMA if B43_BCMA
select SSB if B43_SSB
select FW_LOADER
---help---
b43 is a driver for the Broadcom 43xx series wireless devices.
Check "lspci" for something like
"Broadcom Corporation BCM43XX 802.11 Wireless LAN Controller"
to determine whether you own such a device.
This driver supports the new BCM43xx IEEE 802.11G devices, but not
the old IEEE 802.11B devices. Old devices are supported by
the b43legacy driver.
Note that this has nothing to do with the standard that your AccessPoint
supports (A, B, G or a combination).
IEEE 802.11G devices can talk to IEEE 802.11B AccessPoints.
It is safe to include both b43 and b43legacy as the underlying glue
layer will automatically load the correct version for your device.
This driver uses V4 firmware, which must be installed separately using
b43-fwcutter.
This driver can be built as a module (recommended) that will be called "b43".
If unsure, say M.
config B43_BCMA
bool
config B43_SSB
bool
choice
prompt "Supported bus types"
depends on B43
default B43_BUSES_BCMA_AND_SSB
config B43_BUSES_BCMA_AND_SSB
bool "BCMA and SSB"
depends on BCMA_POSSIBLE && SSB_POSSIBLE
select B43_BCMA
select B43_SSB
config B43_BUSES_BCMA
bool "BCMA only"
depends on BCMA_POSSIBLE
select B43_BCMA
config B43_BUSES_SSB
bool "SSB only"
depends on SSB_POSSIBLE
select B43_SSB
endchoice
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
bool
depends on B43 && SSB_PCIHOST_POSSIBLE
select SSB_PCIHOST
select SSB_B43_PCI_BRIDGE
default y
# Auto-select SSB PCICORE driver, if possible
config B43_PCICORE_AUTOSELECT
bool
depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
select SSB_DRIVER_PCICORE
default y
config B43_SDIO
bool "Broadcom 43xx SDIO device support"
depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
select SSB_SDIOHOST
---help---
Broadcom 43xx device support for Soft-MAC SDIO devices.
With this config option you can drive Soft-MAC b43 cards with a
Secure Digital I/O interface.
This includes the WLAN daughter card found on the Nintendo Wii
video game console.
Note that this does not support Broadcom 43xx Full-MAC devices.
It's safe to select Y here, even if you don't have a B43 SDIO device.
If unsure, say N.
#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 && B43_BCMA
select BCMA_BLOCKIO
default y
config B43_PIO
bool
depends on B43 && B43_SSB
select SSB_BLOCKIO
default y
config B43_PHY_G
bool "Support for G-PHY (802.11g) devices"
depends on B43 && B43_SSB
default y
---help---
This PHY type can be found in the following chipsets:
PCI: BCM4306, BCM4311, BCM4318
SoC: BCM4712, BCM5352E
config B43_PHY_N
bool "Support for N-PHY (the main 802.11n series) devices"
depends on B43
default y
---help---
This PHY type can be found in the following chipsets:
PCI: BCM4321, BCM4322,
BCM43222, BCM43224, BCM43225,
BCM43131, BCM43217, BCM43227, BCM43228
SoC: BCM4716, BCM4717, BCM4718, BCM5356, BCM5357, BCM5358
config B43_PHY_LP
bool "Support for LP-PHY (low-power 802.11g) devices"
depends on B43 && B43_SSB
default y
---help---
The LP-PHY is a low-power PHY built into some notebooks
and embedded devices. It supports 802.11a/b/g
(802.11a support is optional, and currently disabled).
config B43_PHY_HT
bool "Support for HT-PHY (high throughput 802.11n) devices"
depends on B43 && B43_BCMA
default y
---help---
This PHY type with 3x3:3 MIMO can be found in the BCM4331 PCI chipset.
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.
config B43_PHY_AC
bool "Support for AC-PHY (802.11ac) devices (BROKEN)"
depends on B43 && B43_BCMA && BROKEN
---help---
This PHY type can be found in the following chipsets:
PCI: BCM4352, BCM4360
Say N, this is BROKEN and crashes driver.
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
bool
depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
default y
# This config option automatically enables b43 HW-RNG support,
# if the HW-RNG core is enabled.
config B43_HWRNG
bool
depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43)
default y
config B43_DEBUG
bool "Broadcom 43xx debugging"
depends on B43
---help---
Broadcom 43xx debugging.
This adds additional runtime sanity checks and statistics to the driver.
These checks and statistics might be expensive and hurt the runtime
performance of your system.
This also adds the b43 debugfs interface.
Do not enable this, unless you are debugging the driver.
Say N, if you are a distributor or user building a release kernel
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.

View File

@@ -0,0 +1,27 @@
b43-y += main.o
b43-y += bus.o
b43-$(CONFIG_B43_PHY_G) += phy_a.o phy_g.o tables.o lo.o wa.o
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
b43-$(CONFIG_B43_PHY_N) += radio_2056.o
b43-$(CONFIG_B43_PHY_N) += radio_2057.o
b43-y += phy_common.o
b43-$(CONFIG_B43_PHY_N) += phy_n.o
b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
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-$(CONFIG_B43_PHY_AC) += phy_ac.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += dma.o
b43-y += pio.o
b43-y += rfkill.o
b43-y += ppr.o
b43-$(CONFIG_B43_LEDS) += leds.o
b43-$(CONFIG_B43_SDIO) += sdio.o
b43-$(CONFIG_B43_DEBUG) += debugfs.o
obj-$(CONFIG_B43) += b43.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
/*
Broadcom B43 wireless driver
Bus abstraction layer
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
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.
*/
#ifdef CONFIG_BCM47XX_BCMA
#include <asm/mach-bcm47xx/bcm47xx.h>
#endif
#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;
#ifdef CONFIG_BCM47XX_BCMA
if (b43_bus_host_is_pci(dev) &&
bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716)
dev->flush_writes = true;
#endif
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->sprom.board_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
static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
{
return ssb_bus_may_powerdown(dev->sdev->bus);
}
static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
bool dynamic_pctl)
{
return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
}
static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
{
return ssb_device_is_enabled(dev->sdev);
}
static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
u32 core_specific_flags)
{
ssb_device_enable(dev->sdev, core_specific_flags);
}
static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
u32 core_specific_flags)
{
ssb_device_disable(dev->sdev, core_specific_flags);
}
static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
{
return ssb_read16(dev->sdev, offset);
}
static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
{
return ssb_read32(dev->sdev, offset);
}
static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
{
ssb_write16(dev->sdev, offset, value);
}
static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
{
ssb_write32(dev->sdev, offset, value);
}
static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
}
static
void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
}
struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
{
struct b43_bus_dev *dev;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->bus_type = B43_BUS_SSB;
dev->sdev = sdev;
dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown;
dev->bus_powerup = b43_bus_ssb_bus_powerup;
dev->device_is_enabled = b43_bus_ssb_device_is_enabled;
dev->device_enable = b43_bus_ssb_device_enable;
dev->device_disable = b43_bus_ssb_device_disable;
dev->read16 = b43_bus_ssb_read16;
dev->read32 = b43_bus_ssb_read32;
dev->write16 = b43_bus_ssb_write16;
dev->write32 = b43_bus_ssb_write32;
dev->block_read = b43_bus_ssb_block_read;
dev->block_write = b43_bus_ssb_block_write;
dev->dev = sdev->dev;
dev->dma_dev = sdev->dma_dev;
dev->irq = sdev->irq;
dev->board_vendor = sdev->bus->boardinfo.vendor;
dev->board_type = sdev->bus->boardinfo.type;
dev->board_rev = sdev->bus->sprom.board_rev;
dev->chip_id = sdev->bus->chip_id;
dev->chip_rev = sdev->bus->chip_rev;
dev->chip_pkg = sdev->bus->chip_package;
dev->bus_sprom = &sdev->bus->sprom;
dev->core_id = sdev->id.coreid;
dev->core_rev = sdev->id.revision;
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);
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
ssb_set_drvdata(dev->sdev, wldev);
break;
#endif
}
}

View File

@@ -0,0 +1,95 @@
#ifndef B43_BUS_H_
#define B43_BUS_H_
enum b43_bus_type {
#ifdef CONFIG_B43_BCMA
B43_BUS_BCMA,
#endif
#ifdef CONFIG_B43_SSB
B43_BUS_SSB,
#endif
};
struct b43_bus_dev {
enum b43_bus_type bus_type;
union {
struct bcma_device *bdev;
struct ssb_device *sdev;
};
int (*bus_may_powerdown)(struct b43_bus_dev *dev);
int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl);
int (*device_is_enabled)(struct b43_bus_dev *dev);
void (*device_enable)(struct b43_bus_dev *dev,
u32 core_specific_flags);
void (*device_disable)(struct b43_bus_dev *dev,
u32 core_specific_flags);
u16 (*read16)(struct b43_bus_dev *dev, u16 offset);
u32 (*read32)(struct b43_bus_dev *dev, u16 offset);
void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value);
void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value);
void (*block_read)(struct b43_bus_dev *dev, void *buffer,
size_t count, u16 offset, u8 reg_width);
void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width);
bool flush_writes;
struct device *dev;
struct device *dma_dev;
unsigned int irq;
u16 board_vendor;
u16 board_type;
u16 board_rev;
u16 chip_id;
u8 chip_rev;
u8 chip_pkg;
struct ssb_sprom *bus_sprom;
u16 core_id;
u8 core_rev;
};
static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
{
#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
#else
return false;
#endif
};
static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
{
#ifdef CONFIG_B43_BCMA
if (dev->bus_type == B43_BUS_BCMA)
return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
#endif
#ifdef CONFIG_B43_SSB
if (dev->bus_type == B43_BUS_SSB)
return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
#endif
return false;
}
static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
{
#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
#else
return false;
#endif
}
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_ */

View File

@@ -0,0 +1,826 @@
/*
Broadcom B43 wireless driver
debugfs driver debugging code
Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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/fs.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/mutex.h>
#include "b43.h"
#include "main.h"
#include "debugfs.h"
#include "dma.h"
#include "xmit.h"
/* The root directory. */
static struct dentry *rootdir;
struct b43_debugfs_fops {
ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
struct file_operations fops;
/* Offset of struct b43_dfs_file in struct b43_dfsentry */
size_t file_struct_offset;
};
static inline
struct b43_dfs_file *fops_to_dfs_file(struct b43_wldev *dev,
const struct b43_debugfs_fops *dfops)
{
void *p;
p = dev->dfsentry;
p += dfops->file_struct_offset;
return p;
}
#define fappend(fmt, x...) \
do { \
if (bufsize - count) \
count += snprintf(buf + count, \
bufsize - count, \
fmt , ##x); \
else \
printk(KERN_ERR "b43: fappend overflow\n"); \
} while (0)
/* The biggest address values for SHM access from the debugfs files. */
#define B43_MAX_SHM_ROUTING 4
#define B43_MAX_SHM_ADDR 0xFFFF
static ssize_t shm16read__read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
unsigned int routing, addr;
u16 val;
routing = dev->dfsentry->shm16read_routing_next;
addr = dev->dfsentry->shm16read_addr_next;
if ((routing > B43_MAX_SHM_ROUTING) ||
(addr > B43_MAX_SHM_ADDR))
return -EDESTADDRREQ;
val = b43_shm_read16(dev, routing, addr);
fappend("0x%04X\n", val);
return count;
}
static int shm16read__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int routing, addr;
int res;
res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
if (res != 2)
return -EINVAL;
if (routing > B43_MAX_SHM_ROUTING)
return -EADDRNOTAVAIL;
if (addr > B43_MAX_SHM_ADDR)
return -EADDRNOTAVAIL;
if (routing == B43_SHM_SHARED) {
if ((addr % 2) != 0)
return -EADDRNOTAVAIL;
}
dev->dfsentry->shm16read_routing_next = routing;
dev->dfsentry->shm16read_addr_next = addr;
return 0;
}
static int shm16write__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int routing, addr, mask, set;
u16 val;
int res;
res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
&routing, &addr, &mask, &set);
if (res != 4)
return -EINVAL;
if (routing > B43_MAX_SHM_ROUTING)
return -EADDRNOTAVAIL;
if (addr > B43_MAX_SHM_ADDR)
return -EADDRNOTAVAIL;
if (routing == B43_SHM_SHARED) {
if ((addr % 2) != 0)
return -EADDRNOTAVAIL;
}
if ((mask > 0xFFFF) || (set > 0xFFFF))
return -E2BIG;
if (mask == 0)
val = 0;
else
val = b43_shm_read16(dev, routing, addr);
val &= mask;
val |= set;
b43_shm_write16(dev, routing, addr, val);
return 0;
}
static ssize_t shm32read__read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
unsigned int routing, addr;
u32 val;
routing = dev->dfsentry->shm32read_routing_next;
addr = dev->dfsentry->shm32read_addr_next;
if ((routing > B43_MAX_SHM_ROUTING) ||
(addr > B43_MAX_SHM_ADDR))
return -EDESTADDRREQ;
val = b43_shm_read32(dev, routing, addr);
fappend("0x%08X\n", val);
return count;
}
static int shm32read__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int routing, addr;
int res;
res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
if (res != 2)
return -EINVAL;
if (routing > B43_MAX_SHM_ROUTING)
return -EADDRNOTAVAIL;
if (addr > B43_MAX_SHM_ADDR)
return -EADDRNOTAVAIL;
if (routing == B43_SHM_SHARED) {
if ((addr % 2) != 0)
return -EADDRNOTAVAIL;
}
dev->dfsentry->shm32read_routing_next = routing;
dev->dfsentry->shm32read_addr_next = addr;
return 0;
}
static int shm32write__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int routing, addr, mask, set;
u32 val;
int res;
res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
&routing, &addr, &mask, &set);
if (res != 4)
return -EINVAL;
if (routing > B43_MAX_SHM_ROUTING)
return -EADDRNOTAVAIL;
if (addr > B43_MAX_SHM_ADDR)
return -EADDRNOTAVAIL;
if (routing == B43_SHM_SHARED) {
if ((addr % 2) != 0)
return -EADDRNOTAVAIL;
}
if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
return -E2BIG;
if (mask == 0)
val = 0;
else
val = b43_shm_read32(dev, routing, addr);
val &= mask;
val |= set;
b43_shm_write32(dev, routing, addr, val);
return 0;
}
/* The biggest MMIO address that we allow access to from the debugfs files. */
#define B43_MAX_MMIO_ACCESS (0xF00 - 1)
static ssize_t mmio16read__read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
unsigned int addr;
u16 val;
addr = dev->dfsentry->mmio16read_next;
if (addr > B43_MAX_MMIO_ACCESS)
return -EDESTADDRREQ;
val = b43_read16(dev, addr);
fappend("0x%04X\n", val);
return count;
}
static int mmio16read__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int addr;
int res;
res = sscanf(buf, "0x%X", &addr);
if (res != 1)
return -EINVAL;
if (addr > B43_MAX_MMIO_ACCESS)
return -EADDRNOTAVAIL;
if ((addr % 2) != 0)
return -EINVAL;
dev->dfsentry->mmio16read_next = addr;
return 0;
}
static int mmio16write__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int addr, mask, set;
int res;
u16 val;
res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
if (res != 3)
return -EINVAL;
if (addr > B43_MAX_MMIO_ACCESS)
return -EADDRNOTAVAIL;
if ((mask > 0xFFFF) || (set > 0xFFFF))
return -E2BIG;
if ((addr % 2) != 0)
return -EINVAL;
if (mask == 0)
val = 0;
else
val = b43_read16(dev, addr);
val &= mask;
val |= set;
b43_write16(dev, addr, val);
return 0;
}
static ssize_t mmio32read__read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
unsigned int addr;
u32 val;
addr = dev->dfsentry->mmio32read_next;
if (addr > B43_MAX_MMIO_ACCESS)
return -EDESTADDRREQ;
val = b43_read32(dev, addr);
fappend("0x%08X\n", val);
return count;
}
static int mmio32read__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int addr;
int res;
res = sscanf(buf, "0x%X", &addr);
if (res != 1)
return -EINVAL;
if (addr > B43_MAX_MMIO_ACCESS)
return -EADDRNOTAVAIL;
if ((addr % 4) != 0)
return -EINVAL;
dev->dfsentry->mmio32read_next = addr;
return 0;
}
static int mmio32write__write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
unsigned int addr, mask, set;
int res;
u32 val;
res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
if (res != 3)
return -EINVAL;
if (addr > B43_MAX_MMIO_ACCESS)
return -EADDRNOTAVAIL;
if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
return -E2BIG;
if ((addr % 4) != 0)
return -EINVAL;
if (mask == 0)
val = 0;
else
val = b43_read32(dev, addr);
val &= mask;
val |= set;
b43_write32(dev, addr, val);
return 0;
}
static ssize_t txstat_read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
ssize_t count = 0;
int i, idx;
struct b43_txstatus *stat;
if (log->end < 0) {
fappend("Nothing transmitted, yet\n");
goto out;
}
fappend("b43 TX status reports:\n\n"
"index | cookie | seq | phy_stat | frame_count | "
"rts_count | supp_reason | pm_indicated | "
"intermediate | for_ampdu | acked\n" "---\n");
i = log->end + 1;
idx = 0;
while (1) {
if (i == B43_NR_LOGGED_TXSTATUS)
i = 0;
stat = &(log->log[i]);
if (stat->cookie) {
fappend("%03d | "
"0x%04X | 0x%04X | 0x%02X | "
"0x%X | 0x%X | "
"%u | %u | "
"%u | %u | %u\n",
idx,
stat->cookie, stat->seq, stat->phy_stat,
stat->frame_count, stat->rts_count,
stat->supp_reason, stat->pm_indicated,
stat->intermediate, stat->for_ampdu,
stat->acked);
idx++;
}
if (i == log->end)
break;
i++;
}
out:
return count;
}
static int restart_write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
int err = 0;
if (count > 0 && buf[0] == '1') {
b43_controller_restart(dev, "manually restarted");
} else
err = -EINVAL;
return err;
}
static unsigned long calc_expire_secs(unsigned long now,
unsigned long time,
unsigned long expire)
{
expire = time + expire;
if (time_after(now, expire))
return 0; /* expired */
if (expire < now) {
/* jiffies wrapped */
expire -= MAX_JIFFY_OFFSET;
now -= MAX_JIFFY_OFFSET;
}
B43_WARN_ON(expire < now);
return (expire - now) / HZ;
}
static ssize_t loctls_read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
struct b43_txpower_lo_control *lo;
int i, err = 0;
struct b43_lo_calib *cal;
unsigned long now = jiffies;
struct b43_phy *phy = &dev->phy;
if (phy->type != B43_PHYTYPE_G) {
fappend("Device is not a G-PHY\n");
err = -ENODEV;
goto out;
}
lo = phy->g->lo_control;
fappend("-- Local Oscillator calibration data --\n\n");
fappend("HW-power-control enabled: %d\n",
dev->phy.hardware_power_control);
fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n",
lo->tx_bias, lo->tx_magn,
calc_expire_secs(now, lo->txctl_measured_time,
B43_LO_TXCTL_EXPIRE));
fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n",
(unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
(unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL),
calc_expire_secs(now, lo->pwr_vec_read_time,
B43_LO_PWRVEC_EXPIRE));
fappend("\nCalibrated settings:\n");
list_for_each_entry(cal, &lo->calib_list, list) {
bool active;
active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
"(expires in %lu sec)%s\n",
cal->bbatt.att,
cal->rfatt.att, cal->rfatt.with_padmix,
cal->ctl.i, cal->ctl.q,
calc_expire_secs(now, cal->calib_time,
B43_LO_CALIB_EXPIRE),
active ? " ACTIVE" : "");
}
fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n");
for (i = 0; i < lo->rfatt_list.len; i++) {
fappend("%u(%d), ",
lo->rfatt_list.list[i].att,
lo->rfatt_list.list[i].with_padmix);
}
fappend("\n");
fappend("\nUsed Baseband attenuation values:\n");
for (i = 0; i < lo->bbatt_list.len; i++) {
fappend("%u, ",
lo->bbatt_list.list[i].att);
}
fappend("\n");
out:
return err ? err : count;
}
#undef fappend
static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
struct b43_debugfs_fops *dfops;
struct b43_dfs_file *dfile;
ssize_t uninitialized_var(ret);
char *buf;
const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
const size_t buforder = get_order(bufsize);
int err = 0;
if (!count)
return 0;
dev = file->private_data;
if (!dev)
return -ENODEV;
mutex_lock(&dev->wl->mutex);
if (b43_status(dev) < B43_STAT_INITIALIZED) {
err = -ENODEV;
goto out_unlock;
}
dfops = container_of(file->f_op, struct b43_debugfs_fops, fops);
if (!dfops->read) {
err = -ENOSYS;
goto out_unlock;
}
dfile = fops_to_dfs_file(dev, dfops);
if (!dfile->buffer) {
buf = (char *)__get_free_pages(GFP_KERNEL, buforder);
if (!buf) {
err = -ENOMEM;
goto out_unlock;
}
memset(buf, 0, bufsize);
ret = dfops->read(dev, buf, bufsize);
if (ret <= 0) {
free_pages((unsigned long)buf, buforder);
err = ret;
goto out_unlock;
}
dfile->data_len = ret;
dfile->buffer = buf;
}
ret = simple_read_from_buffer(userbuf, count, ppos,
dfile->buffer,
dfile->data_len);
if (*ppos >= dfile->data_len) {
free_pages((unsigned long)dfile->buffer, buforder);
dfile->buffer = NULL;
dfile->data_len = 0;
}
out_unlock:
mutex_unlock(&dev->wl->mutex);
return err ? err : ret;
}
static ssize_t b43_debugfs_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct b43_wldev *dev;
struct b43_debugfs_fops *dfops;
char *buf;
int err = 0;
if (!count)
return 0;
if (count > PAGE_SIZE)
return -E2BIG;
dev = file->private_data;
if (!dev)
return -ENODEV;
mutex_lock(&dev->wl->mutex);
if (b43_status(dev) < B43_STAT_INITIALIZED) {
err = -ENODEV;
goto out_unlock;
}
dfops = container_of(file->f_op, struct b43_debugfs_fops, fops);
if (!dfops->write) {
err = -ENOSYS;
goto out_unlock;
}
buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf) {
err = -ENOMEM;
goto out_unlock;
}
if (copy_from_user(buf, userbuf, count)) {
err = -EFAULT;
goto out_freepage;
}
err = dfops->write(dev, buf, count);
if (err)
goto out_freepage;
out_freepage:
free_page((unsigned long)buf);
out_unlock:
mutex_unlock(&dev->wl->mutex);
return err ? err : count;
}
#define B43_DEBUGFS_FOPS(name, _read, _write) \
static struct b43_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
.fops = { \
.open = simple_open, \
.read = b43_debugfs_read, \
.write = b43_debugfs_write, \
.llseek = generic_file_llseek, \
}, \
.file_struct_offset = offsetof(struct b43_dfsentry, \
file_##name), \
}
B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
{
bool enabled;
enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
if (unlikely(enabled)) {
/* Force full debugging messages, if the user enabled
* some dynamic debugging feature. */
b43_modparam_verbose = B43_VERBOSITY_MAX;
}
return enabled;
}
static void b43_remove_dynamic_debug(struct b43_wldev *dev)
{
struct b43_dfsentry *e = dev->dfsentry;
int i;
for (i = 0; i < __B43_NR_DYNDBG; i++)
debugfs_remove(e->dyn_debug_dentries[i]);
}
static void b43_add_dynamic_debug(struct b43_wldev *dev)
{
struct b43_dfsentry *e = dev->dfsentry;
struct dentry *d;
#define add_dyn_dbg(name, id, initstate) do { \
e->dyn_debug[id] = (initstate); \
d = debugfs_create_bool(name, 0600, e->subdir, \
&(e->dyn_debug[id])); \
if (!IS_ERR(d)) \
e->dyn_debug_dentries[id] = d; \
} while (0)
add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false);
add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false);
add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, false);
add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, false);
add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, false);
add_dyn_dbg("debug_lo", B43_DBG_LO, false);
add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, false);
add_dyn_dbg("debug_keys", B43_DBG_KEYS, false);
add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, false);
#undef add_dyn_dbg
}
void b43_debugfs_add_device(struct b43_wldev *dev)
{
struct b43_dfsentry *e;
struct b43_txstatus_log *log;
char devdir[16];
B43_WARN_ON(!dev);
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) {
b43err(dev->wl, "debugfs: add device OOM\n");
return;
}
e->dev = dev;
log = &e->txstatlog;
log->log = kcalloc(B43_NR_LOGGED_TXSTATUS,
sizeof(struct b43_txstatus), GFP_KERNEL);
if (!log->log) {
b43err(dev->wl, "debugfs: add device txstatus OOM\n");
kfree(e);
return;
}
log->end = -1;
dev->dfsentry = e;
snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
e->subdir = debugfs_create_dir(devdir, rootdir);
if (!e->subdir || IS_ERR(e->subdir)) {
if (e->subdir == ERR_PTR(-ENODEV)) {
b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
"enabled in kernel config\n");
} else {
b43err(dev->wl, "debugfs: cannot create %s directory\n",
devdir);
}
dev->dfsentry = NULL;
kfree(log->log);
kfree(e);
return;
}
e->mmio16read_next = 0xFFFF; /* invalid address */
e->mmio32read_next = 0xFFFF; /* invalid address */
e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */
e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */
e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */
e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */
#define ADD_FILE(name, mode) \
do { \
struct dentry *d; \
d = debugfs_create_file(__stringify(name), \
mode, e->subdir, dev, \
&fops_##name.fops); \
e->file_##name.dentry = NULL; \
if (!IS_ERR(d)) \
e->file_##name.dentry = d; \
} while (0)
ADD_FILE(shm16read, 0600);
ADD_FILE(shm16write, 0200);
ADD_FILE(shm32read, 0600);
ADD_FILE(shm32write, 0200);
ADD_FILE(mmio16read, 0600);
ADD_FILE(mmio16write, 0200);
ADD_FILE(mmio32read, 0600);
ADD_FILE(mmio32write, 0200);
ADD_FILE(txstat, 0400);
ADD_FILE(restart, 0200);
ADD_FILE(loctls, 0400);
#undef ADD_FILE
b43_add_dynamic_debug(dev);
}
void b43_debugfs_remove_device(struct b43_wldev *dev)
{
struct b43_dfsentry *e;
if (!dev)
return;
e = dev->dfsentry;
if (!e)
return;
b43_remove_dynamic_debug(dev);
debugfs_remove(e->file_shm16read.dentry);
debugfs_remove(e->file_shm16write.dentry);
debugfs_remove(e->file_shm32read.dentry);
debugfs_remove(e->file_shm32write.dentry);
debugfs_remove(e->file_mmio16read.dentry);
debugfs_remove(e->file_mmio16write.dentry);
debugfs_remove(e->file_mmio32read.dentry);
debugfs_remove(e->file_mmio32write.dentry);
debugfs_remove(e->file_txstat.dentry);
debugfs_remove(e->file_restart.dentry);
debugfs_remove(e->file_loctls.dentry);
debugfs_remove(e->subdir);
kfree(e->txstatlog.log);
kfree(e);
}
void b43_debugfs_log_txstat(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
struct b43_dfsentry *e = dev->dfsentry;
struct b43_txstatus_log *log;
struct b43_txstatus *cur;
int i;
if (!e)
return;
log = &e->txstatlog;
i = log->end + 1;
if (i == B43_NR_LOGGED_TXSTATUS)
i = 0;
log->end = i;
cur = &(log->log[i]);
memcpy(cur, status, sizeof(*cur));
}
void b43_debugfs_init(void)
{
rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (IS_ERR(rootdir))
rootdir = NULL;
}
void b43_debugfs_exit(void)
{
debugfs_remove(rootdir);
}

View File

@@ -0,0 +1,111 @@
#ifndef B43_DEBUGFS_H_
#define B43_DEBUGFS_H_
struct b43_wldev;
struct b43_txstatus;
enum b43_dyndbg { /* Dynamic debugging features */
B43_DBG_XMITPOWER,
B43_DBG_DMAOVERFLOW,
B43_DBG_DMAVERBOSE,
B43_DBG_PWORK_FAST,
B43_DBG_PWORK_STOP,
B43_DBG_LO,
B43_DBG_FIRMWARE,
B43_DBG_KEYS,
B43_DBG_VERBOSESTATS,
__B43_NR_DYNDBG,
};
#ifdef CONFIG_B43_DEBUG
struct dentry;
#define B43_NR_LOGGED_TXSTATUS 100
struct b43_txstatus_log {
/* This structure is protected by wl->mutex */
struct b43_txstatus *log;
int end;
};
struct b43_dfs_file {
struct dentry *dentry;
char *buffer;
size_t data_len;
};
struct b43_dfsentry {
struct b43_wldev *dev;
struct dentry *subdir;
struct b43_dfs_file file_shm16read;
struct b43_dfs_file file_shm16write;
struct b43_dfs_file file_shm32read;
struct b43_dfs_file file_shm32write;
struct b43_dfs_file file_mmio16read;
struct b43_dfs_file file_mmio16write;
struct b43_dfs_file file_mmio32read;
struct b43_dfs_file file_mmio32write;
struct b43_dfs_file file_txstat;
struct b43_dfs_file file_txpower_g;
struct b43_dfs_file file_restart;
struct b43_dfs_file file_loctls;
struct b43_txstatus_log txstatlog;
/* The cached address for the next mmio16read file read */
u16 mmio16read_next;
/* The cached address for the next mmio32read file read */
u16 mmio32read_next;
/* The cached address for the next shm16read file read */
u32 shm16read_routing_next;
u32 shm16read_addr_next;
/* The cached address for the next shm32read file read */
u32 shm32read_routing_next;
u32 shm32read_addr_next;
/* Enabled/Disabled list for the dynamic debugging features. */
bool dyn_debug[__B43_NR_DYNDBG];
/* Dentries for the dynamic debugging entries. */
struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG];
};
bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature);
void b43_debugfs_init(void);
void b43_debugfs_exit(void);
void b43_debugfs_add_device(struct b43_wldev *dev);
void b43_debugfs_remove_device(struct b43_wldev *dev);
void b43_debugfs_log_txstat(struct b43_wldev *dev,
const struct b43_txstatus *status);
#else /* CONFIG_B43_DEBUG */
static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
{
return false;
}
static inline void b43_debugfs_init(void)
{
}
static inline void b43_debugfs_exit(void)
{
}
static inline void b43_debugfs_add_device(struct b43_wldev *dev)
{
}
static inline void b43_debugfs_remove_device(struct b43_wldev *dev)
{
}
static inline void b43_debugfs_log_txstat(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
}
#endif /* CONFIG_B43_DEBUG */
#endif /* B43_DEBUGFS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
#ifndef B43_DMA_H_
#define B43_DMA_H_
#include <linux/err.h>
#include "b43.h"
/* DMA-Interrupt reasons. */
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
| (1 << 14) | (1 << 15))
#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
#define B43_DMAIRQ_RX_DONE (1 << 16)
/*** 32-bit DMA Engine. ***/
/* 32-bit DMA controller registers. */
#define B43_DMA32_TXCTL 0x00
#define B43_DMA32_TXENABLE 0x00000001
#define B43_DMA32_TXSUSPEND 0x00000002
#define B43_DMA32_TXLOOPBACK 0x00000004
#define B43_DMA32_TXFLUSH 0x00000010
#define B43_DMA32_TXPARITYDISABLE 0x00000800
#define B43_DMA32_TXADDREXT_MASK 0x00030000
#define B43_DMA32_TXADDREXT_SHIFT 16
#define B43_DMA32_TXRING 0x04
#define B43_DMA32_TXINDEX 0x08
#define B43_DMA32_TXSTATUS 0x0C
#define B43_DMA32_TXDPTR 0x00000FFF
#define B43_DMA32_TXSTATE 0x0000F000
#define B43_DMA32_TXSTAT_DISABLED 0x00000000
#define B43_DMA32_TXSTAT_ACTIVE 0x00001000
#define B43_DMA32_TXSTAT_IDLEWAIT 0x00002000
#define B43_DMA32_TXSTAT_STOPPED 0x00003000
#define B43_DMA32_TXSTAT_SUSP 0x00004000
#define B43_DMA32_TXERROR 0x000F0000
#define B43_DMA32_TXERR_NOERR 0x00000000
#define B43_DMA32_TXERR_PROT 0x00010000
#define B43_DMA32_TXERR_UNDERRUN 0x00020000
#define B43_DMA32_TXERR_BUFREAD 0x00030000
#define B43_DMA32_TXERR_DESCREAD 0x00040000
#define B43_DMA32_TXACTIVE 0xFFF00000
#define B43_DMA32_RXCTL 0x10
#define B43_DMA32_RXENABLE 0x00000001
#define B43_DMA32_RXFROFF_MASK 0x000000FE
#define B43_DMA32_RXFROFF_SHIFT 1
#define B43_DMA32_RXDIRECTFIFO 0x00000100
#define B43_DMA32_RXPARITYDISABLE 0x00000800
#define B43_DMA32_RXADDREXT_MASK 0x00030000
#define B43_DMA32_RXADDREXT_SHIFT 16
#define B43_DMA32_RXRING 0x14
#define B43_DMA32_RXINDEX 0x18
#define B43_DMA32_RXSTATUS 0x1C
#define B43_DMA32_RXDPTR 0x00000FFF
#define B43_DMA32_RXSTATE 0x0000F000
#define B43_DMA32_RXSTAT_DISABLED 0x00000000
#define B43_DMA32_RXSTAT_ACTIVE 0x00001000
#define B43_DMA32_RXSTAT_IDLEWAIT 0x00002000
#define B43_DMA32_RXSTAT_STOPPED 0x00003000
#define B43_DMA32_RXERROR 0x000F0000
#define B43_DMA32_RXERR_NOERR 0x00000000
#define B43_DMA32_RXERR_PROT 0x00010000
#define B43_DMA32_RXERR_OVERFLOW 0x00020000
#define B43_DMA32_RXERR_BUFWRITE 0x00030000
#define B43_DMA32_RXERR_DESCREAD 0x00040000
#define B43_DMA32_RXACTIVE 0xFFF00000
/* 32-bit DMA descriptor. */
struct b43_dmadesc32 {
__le32 control;
__le32 address;
} __packed;
#define B43_DMA32_DCTL_BYTECNT 0x00001FFF
#define B43_DMA32_DCTL_ADDREXT_MASK 0x00030000
#define B43_DMA32_DCTL_ADDREXT_SHIFT 16
#define B43_DMA32_DCTL_DTABLEEND 0x10000000
#define B43_DMA32_DCTL_IRQ 0x20000000
#define B43_DMA32_DCTL_FRAMEEND 0x40000000
#define B43_DMA32_DCTL_FRAMESTART 0x80000000
/*** 64-bit DMA Engine. ***/
/* 64-bit DMA controller registers. */
#define B43_DMA64_TXCTL 0x00
#define B43_DMA64_TXENABLE 0x00000001
#define B43_DMA64_TXSUSPEND 0x00000002
#define B43_DMA64_TXLOOPBACK 0x00000004
#define B43_DMA64_TXFLUSH 0x00000010
#define B43_DMA64_TXPARITYDISABLE 0x00000800
#define B43_DMA64_TXADDREXT_MASK 0x00030000
#define B43_DMA64_TXADDREXT_SHIFT 16
#define B43_DMA64_TXINDEX 0x04
#define B43_DMA64_TXRINGLO 0x08
#define B43_DMA64_TXRINGHI 0x0C
#define B43_DMA64_TXSTATUS 0x10
#define B43_DMA64_TXSTATDPTR 0x00001FFF
#define B43_DMA64_TXSTAT 0xF0000000
#define B43_DMA64_TXSTAT_DISABLED 0x00000000
#define B43_DMA64_TXSTAT_ACTIVE 0x10000000
#define B43_DMA64_TXSTAT_IDLEWAIT 0x20000000
#define B43_DMA64_TXSTAT_STOPPED 0x30000000
#define B43_DMA64_TXSTAT_SUSP 0x40000000
#define B43_DMA64_TXERROR 0x14
#define B43_DMA64_TXERRDPTR 0x0001FFFF
#define B43_DMA64_TXERR 0xF0000000
#define B43_DMA64_TXERR_NOERR 0x00000000
#define B43_DMA64_TXERR_PROT 0x10000000
#define B43_DMA64_TXERR_UNDERRUN 0x20000000
#define B43_DMA64_TXERR_TRANSFER 0x30000000
#define B43_DMA64_TXERR_DESCREAD 0x40000000
#define B43_DMA64_TXERR_CORE 0x50000000
#define B43_DMA64_RXCTL 0x20
#define B43_DMA64_RXENABLE 0x00000001
#define B43_DMA64_RXFROFF_MASK 0x000000FE
#define B43_DMA64_RXFROFF_SHIFT 1
#define B43_DMA64_RXDIRECTFIFO 0x00000100
#define B43_DMA64_RXPARITYDISABLE 0x00000800
#define B43_DMA64_RXADDREXT_MASK 0x00030000
#define B43_DMA64_RXADDREXT_SHIFT 16
#define B43_DMA64_RXINDEX 0x24
#define B43_DMA64_RXRINGLO 0x28
#define B43_DMA64_RXRINGHI 0x2C
#define B43_DMA64_RXSTATUS 0x30
#define B43_DMA64_RXSTATDPTR 0x00001FFF
#define B43_DMA64_RXSTAT 0xF0000000
#define B43_DMA64_RXSTAT_DISABLED 0x00000000
#define B43_DMA64_RXSTAT_ACTIVE 0x10000000
#define B43_DMA64_RXSTAT_IDLEWAIT 0x20000000
#define B43_DMA64_RXSTAT_STOPPED 0x30000000
#define B43_DMA64_RXSTAT_SUSP 0x40000000
#define B43_DMA64_RXERROR 0x34
#define B43_DMA64_RXERRDPTR 0x0001FFFF
#define B43_DMA64_RXERR 0xF0000000
#define B43_DMA64_RXERR_NOERR 0x00000000
#define B43_DMA64_RXERR_PROT 0x10000000
#define B43_DMA64_RXERR_UNDERRUN 0x20000000
#define B43_DMA64_RXERR_TRANSFER 0x30000000
#define B43_DMA64_RXERR_DESCREAD 0x40000000
#define B43_DMA64_RXERR_CORE 0x50000000
/* 64-bit DMA descriptor. */
struct b43_dmadesc64 {
__le32 control0;
__le32 control1;
__le32 address_low;
__le32 address_high;
} __packed;
#define B43_DMA64_DCTL0_DTABLEEND 0x10000000
#define B43_DMA64_DCTL0_IRQ 0x20000000
#define B43_DMA64_DCTL0_FRAMEEND 0x40000000
#define B43_DMA64_DCTL0_FRAMESTART 0x80000000
#define B43_DMA64_DCTL1_BYTECNT 0x00001FFF
#define B43_DMA64_DCTL1_ADDREXT_MASK 0x00030000
#define B43_DMA64_DCTL1_ADDREXT_SHIFT 16
struct b43_dmadesc_generic {
union {
struct b43_dmadesc32 dma32;
struct b43_dmadesc64 dma64;
} __packed;
} __packed;
/* Misc DMA constants */
#define B43_DMA32_RINGMEMSIZE 4096
#define B43_DMA64_RINGMEMSIZE 8192
/* Offset of frame with actual data */
#define B43_DMA0_RX_FW598_FO 38
#define B43_DMA0_RX_FW351_FO 30
/* DMA engine tuning knobs */
#define B43_TXRING_SLOTS 256
#define B43_RXRING_SLOTS 256
#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
/* Pointer poison */
#define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM))
#define b43_dma_ptr_is_poisoned(ptr) (unlikely((ptr) == B43_DMA_PTR_POISON))
struct sk_buff;
struct b43_private;
struct b43_txstatus;
struct b43_dmadesc_meta {
/* The kernel DMA-able buffer. */
struct sk_buff *skb;
/* DMA base bus-address of the descriptor buffer. */
dma_addr_t dmaaddr;
/* ieee80211 TX status. Only used once per 802.11 frag. */
bool is_last_fragment;
};
struct b43_dmaring;
/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
struct b43_dma_ops {
struct b43_dmadesc_generic *(*idx2desc) (struct b43_dmaring * ring,
int slot,
struct b43_dmadesc_meta **
meta);
void (*fill_descriptor) (struct b43_dmaring * ring,
struct b43_dmadesc_generic * desc,
dma_addr_t dmaaddr, u16 bufsize, int start,
int end, int irq);
void (*poke_tx) (struct b43_dmaring * ring, int slot);
void (*tx_suspend) (struct b43_dmaring * ring);
void (*tx_resume) (struct b43_dmaring * ring);
int (*get_current_rxslot) (struct b43_dmaring * ring);
void (*set_current_rxslot) (struct b43_dmaring * ring, int slot);
};
enum b43_dmatype {
B43_DMA_30BIT = 30,
B43_DMA_32BIT = 32,
B43_DMA_64BIT = 64,
};
enum b43_addrtype {
B43_DMA_ADDR_LOW,
B43_DMA_ADDR_HIGH,
B43_DMA_ADDR_EXT,
};
struct b43_dmaring {
/* Lowlevel DMA ops. */
const struct b43_dma_ops *ops;
/* Kernel virtual base address of the ring memory. */
void *descbase;
/* Meta data about all descriptors. */
struct b43_dmadesc_meta *meta;
/* Cache of TX headers for each TX frame.
* This is to avoid an allocation on each TX.
* This is NULL for an RX ring.
*/
u8 *txhdr_cache;
/* (Unadjusted) DMA base bus-address of the ring memory. */
dma_addr_t dmabase;
/* Number of descriptor slots in the ring. */
int nr_slots;
/* Number of used descriptor slots. */
int used_slots;
/* Currently used slot in the ring. */
int current_slot;
/* Frameoffset in octets. */
u32 frameoffset;
/* Descriptor buffer size. */
u16 rx_buffersize;
/* The MMIO base register of the DMA controller. */
u16 mmio_base;
/* DMA controller index number (0-5). */
int index;
/* Boolean. Is this a TX ring? */
bool tx;
/* The type of DMA engine used. */
enum b43_dmatype type;
/* Boolean. Is this ring stopped at ieee80211 level? */
bool stopped;
/* The QOS priority assigned to this ring. Only used for TX rings.
* This is the mac80211 "queue" value. */
u8 queue_prio;
struct b43_wldev *dev;
#ifdef CONFIG_B43_DEBUG
/* Maximum number of used slots. */
int max_used_slots;
/* Last time we injected a ring overflow. */
unsigned long last_injected_overflow;
/* Statistics: Number of successfully transmitted packets */
u64 nr_succeed_tx_packets;
/* Statistics: Number of failed TX packets */
u64 nr_failed_tx_packets;
/* Statistics: Total number of TX plus all retries. */
u64 nr_total_packet_tries;
#endif /* CONFIG_B43_DEBUG */
};
static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
{
return b43_read32(ring->dev, ring->mmio_base + offset);
}
static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value)
{
b43_write32(ring->dev, ring->mmio_base + offset, value);
}
int b43_dma_init(struct b43_wldev *dev);
void b43_dma_free(struct b43_wldev *dev);
void b43_dma_tx_suspend(struct b43_wldev *dev);
void b43_dma_tx_resume(struct b43_wldev *dev);
int b43_dma_tx(struct b43_wldev *dev,
struct sk_buff *skb);
void b43_dma_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
void b43_dma_rx(struct b43_dmaring *ring);
void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
unsigned int engine_index, bool enable);
#endif /* B43_DMA_H_ */

View File

@@ -0,0 +1,359 @@
/*
Broadcom B43 wireless driver
LED control
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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 "leds.h"
#include "rfkill.h"
static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
bool activelow)
{
u16 ctl;
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
if (activelow)
ctl &= ~(1 << led_index);
else
ctl |= (1 << led_index);
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
}
static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
bool activelow)
{
u16 ctl;
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
if (activelow)
ctl |= (1 << led_index);
else
ctl &= ~(1 << led_index);
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
}
static void b43_led_update(struct b43_wldev *dev,
struct b43_led *led)
{
bool radio_enabled;
bool turn_on;
if (!led->wl)
return;
radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
/* The led->state read is racy, but we don't care. In case we raced
* with the brightness_set handler, we will be called again soon
* to fixup our state. */
if (radio_enabled)
turn_on = atomic_read(&led->state) != LED_OFF;
else
turn_on = false;
if (turn_on == led->hw_state)
return;
led->hw_state = turn_on;
if (turn_on)
b43_led_turn_on(dev, led->index, led->activelow);
else
b43_led_turn_off(dev, led->index, led->activelow);
}
static void b43_leds_work(struct work_struct *work)
{
struct b43_leds *leds = container_of(work, struct b43_leds, work);
struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
goto out_unlock;
b43_led_update(dev, &wl->leds.led_tx);
b43_led_update(dev, &wl->leds.led_rx);
b43_led_update(dev, &wl->leds.led_radio);
b43_led_update(dev, &wl->leds.led_assoc);
out_unlock:
mutex_unlock(&wl->mutex);
}
/* Callback from the LED subsystem. */
static void b43_led_brightness_set(struct led_classdev *led_dev,
enum led_brightness brightness)
{
struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
struct b43_wl *wl = led->wl;
if (likely(!wl->leds.stop)) {
atomic_set(&led->state, brightness);
ieee80211_queue_work(wl->hw, &wl->leds.work);
}
}
static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
const char *name, const char *default_trigger,
u8 led_index, bool activelow)
{
int err;
if (led->wl)
return -EEXIST;
if (!default_trigger)
return -EINVAL;
led->wl = dev->wl;
led->index = led_index;
led->activelow = activelow;
strncpy(led->name, name, sizeof(led->name));
atomic_set(&led->state, 0);
led->led_dev.name = led->name;
led->led_dev.default_trigger = default_trigger;
led->led_dev.brightness_set = b43_led_brightness_set;
err = led_classdev_register(dev->dev->dev, &led->led_dev);
if (err) {
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
led->wl = NULL;
return err;
}
return 0;
}
static void b43_unregister_led(struct b43_led *led)
{
if (!led->wl)
return;
led_classdev_unregister(&led->led_dev);
led->wl = NULL;
}
static void b43_map_led(struct b43_wldev *dev,
u8 led_index,
enum b43_led_behaviour behaviour,
bool activelow)
{
struct ieee80211_hw *hw = dev->wl->hw;
char name[B43_LED_MAX_NAME_LEN + 1];
/* Map the b43 specific LED behaviour value to the
* generic LED triggers. */
switch (behaviour) {
case B43_LED_INACTIVE:
case B43_LED_OFF:
case B43_LED_ON:
break;
case B43_LED_ACTIVITY:
case B43_LED_TRANSFER:
case B43_LED_APTRANSFER:
snprintf(name, sizeof(name),
"b43-%s::tx", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->wl->leds.led_tx, name,
ieee80211_get_tx_led_name(hw),
led_index, activelow);
snprintf(name, sizeof(name),
"b43-%s::rx", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->wl->leds.led_rx, name,
ieee80211_get_rx_led_name(hw),
led_index, activelow);
break;
case B43_LED_RADIO_ALL:
case B43_LED_RADIO_A:
case B43_LED_RADIO_B:
case B43_LED_MODE_BG:
snprintf(name, sizeof(name),
"b43-%s::radio", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->wl->leds.led_radio, name,
ieee80211_get_radio_led_name(hw),
led_index, activelow);
break;
case B43_LED_WEIRD:
case B43_LED_ASSOC:
snprintf(name, sizeof(name),
"b43-%s::assoc", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->wl->leds.led_assoc, name,
ieee80211_get_assoc_led_name(hw),
led_index, activelow);
break;
default:
b43warn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
behaviour);
break;
}
}
static void b43_led_get_sprominfo(struct b43_wldev *dev,
unsigned int led_index,
enum b43_led_behaviour *behaviour,
bool *activelow)
{
u8 sprom[4];
sprom[0] = dev->dev->bus_sprom->gpio0;
sprom[1] = dev->dev->bus_sprom->gpio1;
sprom[2] = dev->dev->bus_sprom->gpio2;
sprom[3] = dev->dev->bus_sprom->gpio3;
if (sprom[led_index] == 0xFF) {
/* There is no LED information in the SPROM
* for this LED. Hardcode it here. */
*activelow = false;
switch (led_index) {
case 0:
*behaviour = B43_LED_ACTIVITY;
*activelow = true;
if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
*behaviour = B43_LED_RADIO_ALL;
break;
case 1:
*behaviour = B43_LED_RADIO_B;
if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
*behaviour = B43_LED_ASSOC;
break;
case 2:
*behaviour = B43_LED_RADIO_A;
break;
case 3:
*behaviour = B43_LED_OFF;
break;
default:
*behaviour = B43_LED_OFF;
B43_WARN_ON(1);
return;
}
} else {
*behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
*activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
}
}
void b43_leds_init(struct b43_wldev *dev)
{
struct b43_led *led;
unsigned int i;
enum b43_led_behaviour behaviour;
bool activelow;
/* Sync the RF-kill LED state (if we have one) with radio and switch states. */
led = &dev->wl->leds.led_radio;
if (led->wl) {
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
b43_led_turn_on(dev, led->index, led->activelow);
led->hw_state = true;
atomic_set(&led->state, 1);
} else {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = false;
atomic_set(&led->state, 0);
}
}
/* Initialize TX/RX/ASSOC leds */
led = &dev->wl->leds.led_tx;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = false;
atomic_set(&led->state, 0);
}
led = &dev->wl->leds.led_rx;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = false;
atomic_set(&led->state, 0);
}
led = &dev->wl->leds.led_assoc;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = false;
atomic_set(&led->state, 0);
}
/* Initialize other LED states. */
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
switch (behaviour) {
case B43_LED_OFF:
b43_led_turn_off(dev, i, activelow);
break;
case B43_LED_ON:
b43_led_turn_on(dev, i, activelow);
break;
default:
/* Leave others as-is. */
break;
}
}
dev->wl->leds.stop = 0;
}
void b43_leds_exit(struct b43_wldev *dev)
{
struct b43_leds *leds = &dev->wl->leds;
b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
}
void b43_leds_stop(struct b43_wldev *dev)
{
struct b43_leds *leds = &dev->wl->leds;
leds->stop = 1;
cancel_work_sync(&leds->work);
}
void b43_leds_register(struct b43_wldev *dev)
{
unsigned int i;
enum b43_led_behaviour behaviour;
bool activelow;
INIT_WORK(&dev->wl->leds.work, b43_leds_work);
/* Register the LEDs to the LED subsystem. */
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
b43_map_led(dev, i, behaviour, activelow);
}
}
void b43_leds_unregister(struct b43_wl *wl)
{
struct b43_leds *leds = &wl->leds;
b43_unregister_led(&leds->led_tx);
b43_unregister_led(&leds->led_rx);
b43_unregister_led(&leds->led_assoc);
b43_unregister_led(&leds->led_radio);
}

View File

@@ -0,0 +1,94 @@
#ifndef B43_LEDS_H_
#define B43_LEDS_H_
struct b43_wl;
struct b43_wldev;
#ifdef CONFIG_B43_LEDS
#include <linux/types.h>
#include <linux/leds.h>
#include <linux/workqueue.h>
#define B43_LED_MAX_NAME_LEN 31
struct b43_led {
struct b43_wl *wl;
/* The LED class device */
struct led_classdev led_dev;
/* The index number of the LED. */
u8 index;
/* If activelow is true, the LED is ON if the
* bit is switched off. */
bool activelow;
/* The unique name string for this LED device. */
char name[B43_LED_MAX_NAME_LEN + 1];
/* The current status of the LED. This is updated locklessly. */
atomic_t state;
/* The active state in hardware. */
bool hw_state;
};
struct b43_leds {
struct b43_led led_tx;
struct b43_led led_rx;
struct b43_led led_radio;
struct b43_led led_assoc;
bool stop;
struct work_struct work;
};
#define B43_MAX_NR_LEDS 4
#define B43_LED_BEHAVIOUR 0x7F
#define B43_LED_ACTIVELOW 0x80
/* LED behaviour values */
enum b43_led_behaviour {
B43_LED_OFF,
B43_LED_ON,
B43_LED_ACTIVITY,
B43_LED_RADIO_ALL,
B43_LED_RADIO_A,
B43_LED_RADIO_B,
B43_LED_MODE_BG,
B43_LED_TRANSFER,
B43_LED_APTRANSFER,
B43_LED_WEIRD, //FIXME
B43_LED_ASSOC,
B43_LED_INACTIVE,
};
void b43_leds_register(struct b43_wldev *dev);
void b43_leds_unregister(struct b43_wl *wl);
void b43_leds_init(struct b43_wldev *dev);
void b43_leds_exit(struct b43_wldev *dev);
void b43_leds_stop(struct b43_wldev *dev);
#else /* CONFIG_B43_LEDS */
/* LED support disabled */
struct b43_leds {
/* empty */
};
static inline void b43_leds_register(struct b43_wldev *dev)
{
}
static inline void b43_leds_unregister(struct b43_wl *wl)
{
}
static inline void b43_leds_init(struct b43_wldev *dev)
{
}
static inline void b43_leds_exit(struct b43_wldev *dev)
{
}
static inline void b43_leds_stop(struct b43_wldev *dev)
{
}
#endif /* CONFIG_B43_LEDS */
#endif /* B43_LEDS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
#ifndef B43_LO_H_
#define B43_LO_H_
/* G-PHY Local Oscillator */
#include "phy_g.h"
struct b43_wldev;
/* Local Oscillator control value-pair. */
struct b43_loctl {
/* Control values. */
s8 i;
s8 q;
};
/* Debugging: Poison value for i and q values. */
#define B43_LOCTL_POISON 111
/* This struct holds calibrated LO settings for a set of
* Baseband and RF attenuation settings. */
struct b43_lo_calib {
/* The set of attenuation values this set of LO
* control values is calibrated for. */
struct b43_bbatt bbatt;
struct b43_rfatt rfatt;
/* The set of control values for the LO. */
struct b43_loctl ctl;
/* The time when these settings were calibrated (in jiffies) */
unsigned long calib_time;
/* List. */
struct list_head list;
};
/* Size of the DC Lookup Table in 16bit words. */
#define B43_DC_LT_SIZE 32
/* Local Oscillator calibration information */
struct b43_txpower_lo_control {
/* Lists of RF and BB attenuation values for this device.
* Used for building hardware power control tables. */
struct b43_rfatt_list rfatt_list;
struct b43_bbatt_list bbatt_list;
/* The DC Lookup Table is cached in memory here.
* Note that this is only used for Hardware Power Control. */
u16 dc_lt[B43_DC_LT_SIZE];
/* List of calibrated control values (struct b43_lo_calib). */
struct list_head calib_list;
/* Last time the power vector was read (jiffies). */
unsigned long pwr_vec_read_time;
/* Last time the txctl values were measured (jiffies). */
unsigned long txctl_measured_time;
/* Current TX Bias value */
u8 tx_bias;
/* Current TX Magnification Value (if used by the device) */
u8 tx_magn;
/* Saved device PowerVector */
u64 power_vector;
};
/* Calibration expire timeouts.
* Timeouts must be multiple of 15 seconds. To make sure
* the item really expired when the 15 second timer hits, we
* subtract two additional seconds from the timeout. */
#define B43_LO_CALIB_EXPIRE (HZ * (30 - 2))
#define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2))
#define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4))
/* Adjust the Local Oscillator to the saved attenuation
* and txctl values.
*/
void b43_lo_g_adjust(struct b43_wldev *dev);
/* Adjust to specific values. */
void b43_lo_g_adjust_to(struct b43_wldev *dev,
u16 rfatt, u16 bbatt, u16 tx_control);
void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all);
void b43_lo_g_maintenance_work(struct b43_wldev *dev);
void b43_lo_g_cleanup(struct b43_wldev *dev);
void b43_lo_g_init(struct b43_wldev *dev);
#endif /* B43_LO_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
/*
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Some parts of the code in this file are derived from the ipw2200
driver Copyright(c) 2003 - 2004 Intel Corporation.
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.
*/
#ifndef B43_MAIN_H_
#define B43_MAIN_H_
#include "b43.h"
#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
/* Magic helper macro to pad structures. Ignore those above. It's magic. */
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
extern int b43_modparam_verbose;
/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
* you add or remove levels. */
enum b43_verbosity {
B43_VERBOSITY_ERROR,
B43_VERBOSITY_WARN,
B43_VERBOSITY_INFO,
B43_VERBOSITY_DEBUG,
__B43_VERBOSITY_AFTERLAST, /* keep last */
B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1,
#if B43_DEBUG
B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG,
#else
B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO,
#endif
};
static inline int b43_is_cck_rate(int rate)
{
return (rate == B43_CCK_RATE_1MB ||
rate == B43_CCK_RATE_2MB ||
rate == B43_CCK_RATE_5MB || rate == B43_CCK_RATE_11MB);
}
static inline int b43_is_ofdm_rate(int rate)
{
return !b43_is_cck_rate(rate);
}
u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
u8 antenna_nr);
void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
u64 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u64 value);
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
void b43_controller_restart(struct b43_wldev *dev, const char *reason);
#define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */
#define B43_PS_DISABLED (1 << 1) /* Force disable hardware power saving */
#define B43_PS_AWAKE (1 << 2) /* Force device awake */
#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */
void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev);
void b43_mac_suspend(struct b43_wldev *dev);
void b43_mac_enable(struct b43_wldev *dev);
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
struct b43_request_fw_context;
int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name,
struct b43_firmware_file *fw, bool async);
void b43_do_release_fw(struct b43_firmware_file *fw);
#endif /* B43_MAIN_H_ */

View File

@@ -0,0 +1,595 @@
/*
Broadcom B43 wireless driver
IEEE 802.11a PHY driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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_a.h"
#include "phy_common.h"
#include "wa.h"
#include "tables.h"
#include "main.h"
/* Get the freq, as it has to be written to the device. */
static inline u16 channel2freq_a(u8 channel)
{
B43_WARN_ON(channel > 200);
return (5000 + 5 * channel);
}
static inline u16 freq_r3A_value(u16 frequency)
{
u16 value;
if (frequency < 5091)
value = 0x0040;
else if (frequency < 5321)
value = 0x0000;
else if (frequency < 5806)
value = 0x0080;
else
value = 0x0040;
return value;
}
#if 0
/* This function converts a TSSI value to dBm in Q5.2 */
static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
s8 dbm = 0;
s32 tmp;
tmp = (aphy->tgt_idle_tssi - aphy->cur_idle_tssi + tssi);
tmp += 0x80;
tmp = clamp_val(tmp, 0x00, 0xFF);
dbm = aphy->tssi2dbm[tmp];
//TODO: There's a FIXME on the specs
return dbm;
}
#endif
static void b43_radio_set_tx_iq(struct b43_wldev *dev)
{
static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
u16 tmp = b43_radio_read16(dev, 0x001E);
int i, j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
if (tmp == (data_high[i] << 4 | data_low[j])) {
b43_phy_write(dev, 0x0069,
(i - j) << 8 | 0x00C0);
return;
}
}
}
}
static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
{
u16 freq, r8, tmp;
freq = channel2freq_a(channel);
r8 = b43_radio_read16(dev, 0x0008);
b43_write16(dev, 0x03F0, freq);
b43_radio_write16(dev, 0x0008, r8);
//TODO: write max channel TX power? to Radio 0x2D
tmp = b43_radio_read16(dev, 0x002E);
tmp &= 0x0080;
//TODO: OR tmp with the Power out estimation for this channel?
b43_radio_write16(dev, 0x002E, tmp);
if (freq >= 4920 && freq <= 5500) {
/*
* r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
* = (freq * 0.025862069
*/
r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
}
b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
b43_radio_maskset(dev, 0x0022, 0x000F, (r8 << 4));
b43_radio_write16(dev, 0x002A, (r8 << 4));
b43_radio_write16(dev, 0x002B, (r8 << 4));
b43_radio_maskset(dev, 0x0008, 0x00F0, (r8 << 4));
b43_radio_maskset(dev, 0x0029, 0xFF0F, 0x00B0);
b43_radio_write16(dev, 0x0035, 0x00AA);
b43_radio_write16(dev, 0x0036, 0x0085);
b43_radio_maskset(dev, 0x003A, 0xFF20, freq_r3A_value(freq));
b43_radio_mask(dev, 0x003D, 0x00FF);
b43_radio_maskset(dev, 0x0081, 0xFF7F, 0x0080);
b43_radio_mask(dev, 0x0035, 0xFFEF);
b43_radio_maskset(dev, 0x0035, 0xFFEF, 0x0010);
b43_radio_set_tx_iq(dev);
//TODO: TSSI2dbm workaround
//FIXME b43_phy_xmitpower(dev);
}
static void b43_radio_init2060(struct b43_wldev *dev)
{
b43_radio_write16(dev, 0x0004, 0x00C0);
b43_radio_write16(dev, 0x0005, 0x0008);
b43_radio_write16(dev, 0x0009, 0x0040);
b43_radio_write16(dev, 0x0005, 0x00AA);
b43_radio_write16(dev, 0x0032, 0x008F);
b43_radio_write16(dev, 0x0006, 0x008F);
b43_radio_write16(dev, 0x0034, 0x008F);
b43_radio_write16(dev, 0x002C, 0x0007);
b43_radio_write16(dev, 0x0082, 0x0080);
b43_radio_write16(dev, 0x0080, 0x0000);
b43_radio_write16(dev, 0x003F, 0x00DA);
b43_radio_mask(dev, 0x0005, ~0x0008);
b43_radio_mask(dev, 0x0081, ~0x0010);
b43_radio_mask(dev, 0x0081, ~0x0020);
b43_radio_mask(dev, 0x0081, ~0x0020);
msleep(1); /* delay 400usec */
b43_radio_maskset(dev, 0x0081, ~0x0020, 0x0010);
msleep(1); /* delay 400usec */
b43_radio_maskset(dev, 0x0005, ~0x0008, 0x0008);
b43_radio_mask(dev, 0x0085, ~0x0010);
b43_radio_mask(dev, 0x0005, ~0x0008);
b43_radio_mask(dev, 0x0081, ~0x0040);
b43_radio_maskset(dev, 0x0081, ~0x0040, 0x0040);
b43_radio_write16(dev, 0x0005,
(b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
b43_phy_write(dev, 0x0063, 0xDDC6);
b43_phy_write(dev, 0x0069, 0x07BE);
b43_phy_write(dev, 0x006A, 0x0000);
aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev));
msleep(1);
}
static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
{
int i;
if (dev->phy.rev < 3) {
if (enable)
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
b43_ofdmtab_write16(dev,
B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
b43_ofdmtab_write16(dev,
B43_OFDMTAB_WRSSI, i, 0xFFF8);
}
else
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
b43_ofdmtab_write16(dev,
B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
b43_ofdmtab_write16(dev,
B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
}
} else {
if (enable)
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
b43_ofdmtab_write16(dev,
B43_OFDMTAB_WRSSI, i, 0x0820);
else
for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
b43_ofdmtab_write16(dev,
B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
}
}
static void b43_phy_ww(struct b43_wldev *dev)
{
u16 b, curr_s, best_s = 0xFFFF;
int i;
b43_phy_mask(dev, B43_PHY_CRS0, ~B43_PHY_CRS0_EN);
b43_phy_set(dev, B43_PHY_OFDM(0x1B), 0x1000);
b43_phy_maskset(dev, B43_PHY_OFDM(0x82), 0xF0FF, 0x0300);
b43_radio_set(dev, 0x0009, 0x0080);
b43_radio_maskset(dev, 0x0012, 0xFFFC, 0x0002);
b43_wa_initgains(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
b = b43_phy_read(dev, B43_PHY_PWRDOWN);
b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
b43_radio_set(dev, 0x0004, 0x0004);
for (i = 0x10; i <= 0x20; i++) {
b43_radio_write16(dev, 0x0013, i);
curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
if (!curr_s) {
best_s = 0x0000;
break;
} else if (curr_s >= 0x0080)
curr_s = 0x0100 - curr_s;
if (curr_s < best_s)
best_s = curr_s;
}
b43_phy_write(dev, B43_PHY_PWRDOWN, b);
b43_radio_mask(dev, 0x0004, 0xFFFB);
b43_radio_write16(dev, 0x0013, best_s);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
b43_phy_maskset(dev, B43_PHY_OFDM(0xBB), 0xF000, 0x0053);
b43_phy_maskset(dev, B43_PHY_OFDM61, 0xFE1F, 0x0120);
b43_phy_maskset(dev, B43_PHY_OFDM(0x13), 0x0FFF, 0x3000);
b43_phy_maskset(dev, B43_PHY_OFDM(0x14), 0x0FFF, 0x3000);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
for (i = 0; i < 6; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
}
static void hardware_pctl_init_aphy(struct b43_wldev *dev)
{
//TODO
}
void b43_phy_inita(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
/* This lowlevel A-PHY init is also called from G-PHY init.
* So we must not access phy->a, if called from G-PHY code.
*/
B43_WARN_ON((phy->type != B43_PHYTYPE_A) &&
(phy->type != B43_PHYTYPE_G));
might_sleep();
if (phy->rev >= 6) {
if (phy->type == B43_PHYTYPE_A)
b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x1000);
if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
b43_phy_set(dev, B43_PHY_ENCORE, 0x0010);
else
b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010);
}
b43_wa_all(dev);
if (phy->type == B43_PHYTYPE_A) {
if (phy->gmode && (phy->rev < 3))
b43_phy_set(dev, 0x0034, 0x0001);
b43_phy_rssiagc(dev, 0);
b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
b43_radio_init2060(dev);
if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
((dev->dev->board_type == SSB_BOARD_BU4306) ||
(dev->dev->board_type == SSB_BOARD_BU4309))) {
; //TODO: A PHY LO
}
if (phy->rev >= 3)
b43_phy_ww(dev);
hardware_pctl_init_aphy(dev);
//TODO: radar detection
}
if ((phy->type == B43_PHYTYPE_G) &&
(dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
/* Initialise the TSSI->dBm lookup table */
static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
s16 pab0, pab1, pab2;
pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
(s8) dev->dev->bus_sprom->itssi_a != -1)
aphy->tgt_idle_tssi =
(s8) (dev->dev->bus_sprom->itssi_a);
else
aphy->tgt_idle_tssi = 62;
aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
pab1, pab2);
if (!aphy->tssi2dbm)
return -ENOMEM;
} else {
/* pabX values not set in SPROM,
* but APHY needs a generated table. */
aphy->tssi2dbm = NULL;
b43err(dev->wl, "Could not generate tssi2dBm "
"table (wrong SPROM info)!\n");
return -ENODEV;
}
return 0;
}
static int b43_aphy_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_a *aphy;
int err;
aphy = kzalloc(sizeof(*aphy), GFP_KERNEL);
if (!aphy)
return -ENOMEM;
dev->phy.a = aphy;
err = b43_aphy_init_tssi2dbm_table(dev);
if (err)
goto err_free_aphy;
return 0;
err_free_aphy:
kfree(aphy);
dev->phy.a = NULL;
return err;
}
static void b43_aphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
const void *tssi2dbm;
int tgt_idle_tssi;
/* tssi2dbm table is constant, so it is initialized at alloc time.
* Save a copy of the pointer. */
tssi2dbm = aphy->tssi2dbm;
tgt_idle_tssi = aphy->tgt_idle_tssi;
/* Zero out the whole PHY structure. */
memset(aphy, 0, sizeof(*aphy));
aphy->tssi2dbm = tssi2dbm;
aphy->tgt_idle_tssi = tgt_idle_tssi;
//TODO init struct b43_phy_a
}
static void b43_aphy_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
kfree(aphy->tssi2dbm);
aphy->tssi2dbm = NULL;
kfree(aphy);
dev->phy.a = NULL;
}
static int b43_aphy_op_init(struct b43_wldev *dev)
{
b43_phy_inita(dev);
return 0;
}
static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
{
/* OFDM registers are base-registers for the A-PHY. */
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
offset &= ~B43_PHYROUTE;
offset |= B43_PHYROUTE_BASE;
}
#if B43_DEBUG
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
/* Ext-G registers are only available on G-PHYs */
b43err(dev->wl, "Invalid EXT-G PHY access at "
"0x%04X on A-PHY\n", offset);
dump_stack();
}
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
/* N-BMODE registers are only available on N-PHYs */
b43err(dev->wl, "Invalid N-BMODE PHY access at "
"0x%04X on A-PHY\n", offset);
dump_stack();
}
#endif /* B43_DEBUG */
return offset;
}
static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
{
reg = adjust_phyreg(dev, reg);
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
return b43_read16(dev, B43_MMIO_PHY_DATA);
}
static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
{
reg = adjust_phyreg(dev, reg);
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA, value);
}
static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* Register 1 is a 32-bit register. */
B43_WARN_ON(reg == 1);
/* A-PHY needs 0x40 for read access */
reg |= 0x40;
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
}
static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
{
/* Register 1 is a 32-bit register. */
B43_WARN_ON(reg == 1);
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
}
static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
{
return (dev->phy.rev >= 5);
}
static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
struct b43_phy *phy = &dev->phy;
if (!blocked) {
if (phy->radio_on)
return;
b43_radio_write16(dev, 0x0004, 0x00C0);
b43_radio_write16(dev, 0x0005, 0x0008);
b43_phy_mask(dev, 0x0010, 0xFFF7);
b43_phy_mask(dev, 0x0011, 0xFFF7);
b43_radio_init2060(dev);
} else {
b43_radio_write16(dev, 0x0004, 0x00FF);
b43_radio_write16(dev, 0x0005, 0x00FB);
b43_phy_set(dev, 0x0010, 0x0008);
b43_phy_set(dev, 0x0011, 0x0008);
}
}
static int b43_aphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
if (new_channel > 200)
return -EINVAL;
aphy_channel_switch(dev, new_channel);
return 0;
}
static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev)
{
return 36; /* Default to channel 36 */
}
static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{//TODO
struct b43_phy *phy = &dev->phy;
u16 tmp;
int autodiv = 0;
if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
autodiv = 1;
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,
(autodiv ? B43_ANTENNA_AUTO1 : antenna) <<
B43_PHY_BBANDCFG_RXANT_SHIFT);
if (autodiv) {
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
if (antenna == B43_ANTENNA_AUTO1)
tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
else
tmp |= B43_PHY_ANTDWELL_AUTODIV1;
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
}
if (phy->rev < 3)
b43_phy_maskset(dev, B43_PHY_ANTDWELL, 0xFF00, 0x24);
else {
b43_phy_set(dev, B43_PHY_OFDM61, 0x10);
if (phy->rev == 3) {
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x1D);
b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);
} else {
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x3A);
b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);
}
}
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
}
static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)
{//TODO
}
static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev,
bool ignore_tssi)
{//TODO
return B43_TXPWR_RES_DONE;
}
static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev)
{//TODO
}
static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
{//TODO
}
static const struct b43_phy_operations b43_phyops_a = {
.allocate = b43_aphy_op_allocate,
.free = b43_aphy_op_free,
.prepare_structs = b43_aphy_op_prepare_structs,
.init = b43_aphy_op_init,
.phy_read = b43_aphy_op_read,
.phy_write = b43_aphy_op_write,
.radio_read = b43_aphy_op_radio_read,
.radio_write = b43_aphy_op_radio_write,
.supports_hwpctl = b43_aphy_op_supports_hwpctl,
.software_rfkill = b43_aphy_op_software_rfkill,
.switch_analog = b43_phyop_switch_analog_generic,
.switch_channel = b43_aphy_op_switch_channel,
.get_default_chan = b43_aphy_op_get_default_chan,
.set_rx_antenna = b43_aphy_op_set_rx_antenna,
.recalc_txpower = b43_aphy_op_recalc_txpower,
.adjust_txpower = b43_aphy_op_adjust_txpower,
.pwork_15sec = b43_aphy_op_pwork_15sec,
.pwork_60sec = b43_aphy_op_pwork_60sec,
};

View File

@@ -0,0 +1,126 @@
#ifndef LINUX_B43_PHY_A_H_
#define LINUX_B43_PHY_A_H_
#include "phy_common.h"
/* OFDM (A) PHY Registers */
#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
#define B43_PHY_CRS0_EN 0x4000
#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
#define B43_PHY_LMS B43_PHY_OFDM(0x55)
#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
#define B43_PHY_OTABLENR_SHIFT 10
#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
/*** OFDM table numbers ***/
#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
u16 offset, u16 value);
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
u16 offset, u32 value);
struct b43_phy_a {
/* Pointer to the table used to convert a
* TSSI value to dBm-Q5.2 */
const s8 *tssi2dbm;
/* Target idle TSSI */
int tgt_idle_tssi;
/* Current idle TSSI */
int cur_idle_tssi;//FIXME value currently not set
/* A-PHY TX Power control value. */
u16 txpwr_offset;
//TODO lots of missing stuff
};
/**
* b43_phy_inita - Lowlevel A-PHY init routine.
* This is _only_ used by the G-PHY code.
*/
void b43_phy_inita(struct b43_wldev *dev);
#endif /* LINUX_B43_PHY_A_H_ */

View File

@@ -0,0 +1,92 @@
/*
* Broadcom B43 wireless driver
* IEEE 802.11ac AC-PHY support
*
* Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com>
*
* 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.
*/
#include "b43.h"
#include "phy_ac.h"
/**************************************************
* Basic PHY ops
**************************************************/
static int b43_phy_ac_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_ac *phy_ac;
phy_ac = kzalloc(sizeof(*phy_ac), GFP_KERNEL);
if (!phy_ac)
return -ENOMEM;
dev->phy.ac = phy_ac;
return 0;
}
static void b43_phy_ac_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_ac *phy_ac = phy->ac;
kfree(phy_ac);
phy->ac = NULL;
}
static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
u16 set)
{
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA,
(b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
}
static u16 b43_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg)
{
b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg,
u16 value)
{
b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
}
static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
return 11;
return 36;
}
static enum b43_txpwr_result
b43_phy_ac_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
{
return B43_TXPWR_RES_DONE;
}
static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev)
{
}
/**************************************************
* PHY ops struct
**************************************************/
const struct b43_phy_operations b43_phyops_ac = {
.allocate = b43_phy_ac_op_allocate,
.free = b43_phy_ac_op_free,
.phy_maskset = b43_phy_ac_op_maskset,
.radio_read = b43_phy_ac_op_radio_read,
.radio_write = b43_phy_ac_op_radio_write,
.get_default_chan = b43_phy_ac_op_get_default_chan,
.recalc_txpower = b43_phy_ac_op_recalc_txpower,
.adjust_txpower = b43_phy_ac_op_adjust_txpower,
};

View File

@@ -0,0 +1,38 @@
#ifndef B43_PHY_AC_H_
#define B43_PHY_AC_H_
#include "phy_common.h"
#define B43_PHY_AC_BBCFG 0x001
#define B43_PHY_AC_BBCFG_RSTCCA 0x4000 /* Reset CCA */
#define B43_PHY_AC_BANDCTL 0x003 /* Band control */
#define B43_PHY_AC_BANDCTL_5GHZ 0x0001
#define B43_PHY_AC_TABLE_ID 0x00d
#define B43_PHY_AC_TABLE_OFFSET 0x00e
#define B43_PHY_AC_TABLE_DATA1 0x00f
#define B43_PHY_AC_TABLE_DATA2 0x010
#define B43_PHY_AC_TABLE_DATA3 0x011
#define B43_PHY_AC_CLASSCTL 0x140 /* Classifier control */
#define B43_PHY_AC_CLASSCTL_CCKEN 0x0001 /* CCK enable */
#define B43_PHY_AC_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */
#define B43_PHY_AC_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */
#define B43_PHY_AC_BW1A 0x371
#define B43_PHY_AC_BW2 0x372
#define B43_PHY_AC_BW3 0x373
#define B43_PHY_AC_BW4 0x374
#define B43_PHY_AC_BW5 0x375
#define B43_PHY_AC_BW6 0x376
#define B43_PHY_AC_RFCTL_CMD 0x408
#define B43_PHY_AC_C1_CLIP 0x6d4
#define B43_PHY_AC_C1_CLIP_DIS 0x4000
#define B43_PHY_AC_C2_CLIP 0x8d4
#define B43_PHY_AC_C2_CLIP_DIS 0x4000
#define B43_PHY_AC_C3_CLIP 0xad4
#define B43_PHY_AC_C3_CLIP_DIS 0x4000
struct b43_phy_ac {
};
extern const struct b43_phy_operations b43_phyops_ac;
#endif /* B43_PHY_AC_H_ */

View File

@@ -0,0 +1,653 @@
/*
Broadcom B43 wireless driver
Common PHY routines
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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 "phy_common.h"
#include "phy_g.h"
#include "phy_a.h"
#include "phy_n.h"
#include "phy_lp.h"
#include "phy_ht.h"
#include "phy_lcn.h"
#include "phy_ac.h"
#include "b43.h"
#include "main.h"
int b43_phy_allocate(struct b43_wldev *dev)
{
struct b43_phy *phy = &(dev->phy);
int err;
phy->ops = NULL;
switch (phy->type) {
case B43_PHYTYPE_G:
#ifdef CONFIG_B43_PHY_G
phy->ops = &b43_phyops_g;
#endif
break;
case B43_PHYTYPE_N:
#ifdef CONFIG_B43_PHY_N
phy->ops = &b43_phyops_n;
#endif
break;
case B43_PHYTYPE_LP:
#ifdef CONFIG_B43_PHY_LP
phy->ops = &b43_phyops_lp;
#endif
break;
case B43_PHYTYPE_HT:
#ifdef CONFIG_B43_PHY_HT
phy->ops = &b43_phyops_ht;
#endif
break;
case B43_PHYTYPE_LCN:
#ifdef CONFIG_B43_PHY_LCN
phy->ops = &b43_phyops_lcn;
#endif
break;
case B43_PHYTYPE_AC:
#ifdef CONFIG_B43_PHY_AC
phy->ops = &b43_phyops_ac;
#endif
break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
err = phy->ops->allocate(dev);
if (err)
phy->ops = NULL;
return err;
}
void b43_phy_free(struct b43_wldev *dev)
{
dev->phy.ops->free(dev);
dev->phy.ops = NULL;
}
int b43_phy_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
const struct b43_phy_operations *ops = phy->ops;
int err;
/* During PHY init we need to use some channel. On the first init this
* function is called *before* b43_op_config, so our pointer is NULL.
*/
if (!phy->chandef) {
phy->chandef = &dev->wl->hw->conf.chandef;
phy->channel = phy->chandef->chan->hw_value;
}
phy->ops->switch_analog(dev, true);
b43_software_rfkill(dev, false);
err = ops->init(dev);
if (err) {
b43err(dev->wl, "PHY init failed\n");
goto err_block_rf;
}
phy->do_full_init = false;
err = b43_switch_channel(dev, phy->channel);
if (err) {
b43err(dev->wl, "PHY init: Channel switch to default failed\n");
goto err_phy_exit;
}
return 0;
err_phy_exit:
phy->do_full_init = true;
if (ops->exit)
ops->exit(dev);
err_block_rf:
b43_software_rfkill(dev, true);
return err;
}
void b43_phy_exit(struct b43_wldev *dev)
{
const struct b43_phy_operations *ops = dev->phy.ops;
b43_software_rfkill(dev, true);
dev->phy.do_full_init = true;
if (ops->exit)
ops->exit(dev);
}
bool b43_has_hardware_pctl(struct b43_wldev *dev)
{
if (!dev->phy.hardware_power_control)
return false;
if (!dev->phy.ops->supports_hwpctl)
return false;
return dev->phy.ops->supports_hwpctl(dev);
}
void b43_radio_lock(struct b43_wldev *dev)
{
u32 macctl;
#if B43_DEBUG
B43_WARN_ON(dev->phy.radio_locked);
dev->phy.radio_locked = true;
#endif
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl |= B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit the write and wait for the firmware
* to finish any radio register access. */
b43_read32(dev, B43_MMIO_MACCTL);
udelay(10);
}
void b43_radio_unlock(struct b43_wldev *dev)
{
u32 macctl;
#if B43_DEBUG
B43_WARN_ON(!dev->phy.radio_locked);
dev->phy.radio_locked = false;
#endif
/* Commit any write */
b43_read16(dev, B43_MMIO_PHY_VER);
/* unlock */
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
}
void b43_phy_lock(struct b43_wldev *dev)
{
#if B43_DEBUG
B43_WARN_ON(dev->phy.phy_locked);
dev->phy.phy_locked = true;
#endif
B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
}
void b43_phy_unlock(struct b43_wldev *dev)
{
#if B43_DEBUG
B43_WARN_ON(!dev->phy.phy_locked);
dev->phy.phy_locked = false;
#endif
B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
}
static inline void assert_mac_suspended(struct b43_wldev *dev)
{
if (!B43_DEBUG)
return;
if ((b43_status(dev) >= B43_STAT_INITIALIZED) &&
(dev->mac_suspended <= 0)) {
b43dbg(dev->wl, "PHY/RADIO register access with "
"enabled MAC.\n");
dump_stack();
}
}
u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
{
assert_mac_suspended(dev);
dev->phy.writes_counter = 0;
return dev->phy.ops->radio_read(dev, reg);
}
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
{
assert_mac_suspended(dev);
if (b43_bus_host_is_pci(dev->dev) &&
++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) {
b43_read32(dev, B43_MMIO_MACCTL);
dev->phy.writes_counter = 1;
}
dev->phy.ops->radio_write(dev, reg, value);
}
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
{
b43_radio_write16(dev, offset,
b43_radio_read16(dev, offset) & mask);
}
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
{
b43_radio_write16(dev, offset,
b43_radio_read16(dev, offset) | set);
}
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
{
b43_radio_write16(dev, offset,
(b43_radio_read16(dev, offset) & mask) | set);
}
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
u16 value, int delay, int timeout)
{
u16 val;
int i;
for (i = 0; i < timeout; i += delay) {
val = b43_radio_read(dev, offset);
if ((val & mask) == value)
return true;
udelay(delay);
}
return false;
}
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
{
assert_mac_suspended(dev);
dev->phy.writes_counter = 0;
if (dev->phy.ops->phy_read)
return dev->phy.ops->phy_read(dev, reg);
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
return b43_read16(dev, B43_MMIO_PHY_DATA);
}
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
{
assert_mac_suspended(dev);
if (b43_bus_host_is_pci(dev->dev) &&
++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) {
b43_read16(dev, B43_MMIO_PHY_VER);
dev->phy.writes_counter = 1;
}
if (dev->phy.ops->phy_write)
return dev->phy.ops->phy_write(dev, reg, value);
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA, value);
}
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
{
b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
}
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
{
if (dev->phy.ops->phy_maskset) {
assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, mask, 0);
} else {
b43_phy_write(dev, offset,
b43_phy_read(dev, offset) & mask);
}
}
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
{
if (dev->phy.ops->phy_maskset) {
assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
} else {
b43_phy_write(dev, offset,
b43_phy_read(dev, offset) | set);
}
}
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
{
if (dev->phy.ops->phy_maskset) {
assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, mask, set);
} else {
b43_phy_write(dev, offset,
(b43_phy_read(dev, offset) & mask) | set);
}
}
void b43_phy_put_into_reset(struct b43_wldev *dev)
{
u32 tmp;
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
tmp &= ~B43_BCMA_IOCTL_GMODE;
tmp |= B43_BCMA_IOCTL_PHY_RESET;
tmp |= BCMA_IOCTL_FGC;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
udelay(1);
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
tmp &= ~BCMA_IOCTL_FGC;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
udelay(1);
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);
usleep_range(1000, 2000);
tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
tmp &= ~SSB_TMSLOW_FGC;
ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
usleep_range(1000, 2000);
break;
#endif
}
}
void b43_phy_take_out_of_reset(struct b43_wldev *dev)
{
u32 tmp;
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
/* Unset reset bit (with forcing clock) */
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
tmp &= ~B43_BCMA_IOCTL_PHY_RESET;
tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN;
tmp |= BCMA_IOCTL_FGC;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
udelay(1);
/* Do not force clock anymore */
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
tmp &= ~BCMA_IOCTL_FGC;
tmp |= B43_BCMA_IOCTL_PHY_CLKEN;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
udelay(1);
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
/* Unset reset bit (with forcing clock) */
tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
tmp &= ~B43_TMSLOW_PHYRESET;
tmp &= ~B43_TMSLOW_PHYCLKEN;
tmp |= SSB_TMSLOW_FGC;
ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
usleep_range(1000, 2000);
tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
tmp &= ~SSB_TMSLOW_FGC;
tmp |= B43_TMSLOW_PHYCLKEN;
ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
usleep_range(1000, 2000);
break;
#endif
}
}
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
{
struct b43_phy *phy = &(dev->phy);
u16 channelcookie, savedcookie;
int err;
/* First we set the channel radio code to prevent the
* firmware from sending ghost packets.
*/
channelcookie = new_channel;
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
channelcookie |= B43_SHM_SH_CHAN_5GHZ;
/* FIXME: set 40Mhz flag if required */
if (0)
channelcookie |= B43_SHM_SH_CHAN_40MHZ;
savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
/* Now try to switch the PHY hardware channel. */
err = phy->ops->switch_channel(dev, new_channel);
if (err)
goto err_restore_cookie;
/* Wait for the radio to tune to the channel and stabilize. */
msleep(8);
return 0;
err_restore_cookie:
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_CHAN, savedcookie);
return err;
}
void b43_software_rfkill(struct b43_wldev *dev, bool blocked)
{
struct b43_phy *phy = &dev->phy;
b43_mac_suspend(dev);
phy->ops->software_rfkill(dev, blocked);
phy->radio_on = !blocked;
b43_mac_enable(dev);
}
/**
* b43_phy_txpower_adjust_work - TX power workqueue.
*
* Workqueue for updating the TX power parameters in hardware.
*/
void b43_phy_txpower_adjust_work(struct work_struct *work)
{
struct b43_wl *wl = container_of(work, struct b43_wl,
txpower_adjust_work);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
dev->phy.ops->adjust_txpower(dev);
mutex_unlock(&wl->mutex);
}
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
{
struct b43_phy *phy = &dev->phy;
unsigned long now = jiffies;
enum b43_txpwr_result result;
if (!(flags & B43_TXPWR_IGNORE_TIME)) {
/* Check if it's time for a TXpower check. */
if (time_before(now, phy->next_txpwr_check_time))
return; /* Not yet */
}
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
(dev->dev->board_type == SSB_BOARD_BU4306))
return; /* No software txpower adjustment needed */
result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
if (result == B43_TXPWR_RES_DONE)
return; /* We are done. */
B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
B43_WARN_ON(phy->ops->adjust_txpower == NULL);
/* We must adjust the transmission power in hardware.
* Schedule b43_phy_txpower_adjust_work(). */
ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
}
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
{
const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
unsigned int a, b, c, d;
unsigned int average;
u32 tmp;
tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
a = tmp & 0xFF;
b = (tmp >> 8) & 0xFF;
c = (tmp >> 16) & 0xFF;
d = (tmp >> 24) & 0xFF;
if (a == 0 || a == B43_TSSI_MAX ||
b == 0 || b == B43_TSSI_MAX ||
c == 0 || c == B43_TSSI_MAX ||
d == 0 || d == B43_TSSI_MAX)
return -ENOENT;
/* The values are OK. Clear them. */
tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
(B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);
if (is_ofdm) {
a = (a + 32) & 0x3F;
b = (b + 32) & 0x3F;
c = (c + 32) & 0x3F;
d = (d + 32) & 0x3F;
}
/* Get the average of the values with 0.5 added to each value. */
average = (a + b + c + d + 2) / 4;
if (is_ofdm) {
/* Adjust for CCK-boost */
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1)
& B43_HF_CCKBOOST)
average = (average >= 13) ? (average - 13) : 0;
}
return average;
}
void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
{
b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
}
bool b43_is_40mhz(struct b43_wldev *dev)
{
return dev->phy.chandef->width == NL80211_CHAN_WIDTH_40;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
void b43_phy_force_clock(struct b43_wldev *dev, bool force)
{
u32 tmp;
WARN_ON(dev->phy.type != B43_PHYTYPE_N &&
dev->phy.type != B43_PHYTYPE_HT &&
dev->phy.type != B43_PHYTYPE_AC);
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
if (force)
tmp |= BCMA_IOCTL_FGC;
else
tmp &= ~BCMA_IOCTL_FGC;
bcma_awrite32(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/Cordic */
struct b43_c32 b43_cordic(int theta)
{
static const u32 arctg[] = {
2949120, 1740967, 919879, 466945, 234379, 117304,
58666, 29335, 14668, 7334, 3667, 1833,
917, 458, 229, 115, 57, 29,
};
u8 i;
s32 tmp;
s8 signx = 1;
u32 angle = 0;
struct b43_c32 ret = { .i = 39797, .q = 0, };
while (theta > (180 << 16))
theta -= (360 << 16);
while (theta < -(180 << 16))
theta += (360 << 16);
if (theta > (90 << 16)) {
theta -= (180 << 16);
signx = -1;
} else if (theta < -(90 << 16)) {
theta += (180 << 16);
signx = -1;
}
for (i = 0; i <= 17; i++) {
if (theta > angle) {
tmp = ret.i - (ret.q >> i);
ret.q += ret.i >> i;
ret.i = tmp;
angle += arctg[i];
} else {
tmp = ret.i + (ret.q >> i);
ret.q -= ret.i >> i;
ret.i = tmp;
angle -= arctg[i];
}
}
ret.i *= signx;
ret.q *= signx;
return ret;
}

View File

@@ -0,0 +1,457 @@
#ifndef LINUX_B43_PHY_COMMON_H_
#define LINUX_B43_PHY_COMMON_H_
#include <linux/types.h>
#include <linux/nl80211.h>
struct b43_wldev;
/* Complex number using 2 32-bit signed integers */
struct b43_c32 { s32 i, q; };
#define CORDIC_CONVERT(value) (((value) >= 0) ? \
((((value) >> 15) + 1) >> 1) : \
-((((-(value)) >> 15) + 1) >> 1))
/* PHY register routing bits */
#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
/* CCK (B-PHY) registers. */
#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
/* N-PHY registers. */
#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
/* N-PHY BMODE registers. */
#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
/* OFDM (A-PHY) registers. */
#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
/* Extended G-PHY registers. */
#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
/* Masks for the PHY versioning registers. */
#define B43_PHYVER_ANALOG 0xF000
#define B43_PHYVER_ANALOG_SHIFT 12
#define B43_PHYVER_TYPE 0x0F00
#define B43_PHYVER_TYPE_SHIFT 8
#define B43_PHYVER_VERSION 0x00FF
/* PHY writes need to be flushed if we reach limit */
#define B43_MAX_WRITES_IN_ROW 24
/**
* enum b43_interference_mitigation - Interference Mitigation mode
*
* @B43_INTERFMODE_NONE: Disabled
* @B43_INTERFMODE_NONWLAN: Non-WLAN Interference Mitigation
* @B43_INTERFMODE_MANUALWLAN: WLAN Interference Mitigation
* @B43_INTERFMODE_AUTOWLAN: Automatic WLAN Interference Mitigation
*/
enum b43_interference_mitigation {
B43_INTERFMODE_NONE,
B43_INTERFMODE_NONWLAN,
B43_INTERFMODE_MANUALWLAN,
B43_INTERFMODE_AUTOWLAN,
};
/* Antenna identifiers */
enum {
B43_ANTENNA0 = 0, /* Antenna 0 */
B43_ANTENNA1 = 1, /* Antenna 1 */
B43_ANTENNA_AUTO0 = 2, /* Automatic, starting with antenna 0 */
B43_ANTENNA_AUTO1 = 3, /* Automatic, starting with antenna 1 */
B43_ANTENNA2 = 4,
B43_ANTENNA3 = 8,
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
};
/**
* enum b43_txpwr_result - Return value for the recalc_txpower PHY op.
*
* @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed.
* @B43_TXPWR_RES_DONE: No more work to do. Everything is done.
*/
enum b43_txpwr_result {
B43_TXPWR_RES_NEED_ADJUST,
B43_TXPWR_RES_DONE,
};
/**
* struct b43_phy_operations - Function pointers for PHY ops.
*
* @allocate: Allocate and initialise the PHY data structures.
* Must not be NULL.
* @free: Destroy and free the PHY data structures.
* Must not be NULL.
*
* @prepare_structs: Prepare the PHY data structures.
* The data structures allocated in @allocate are
* initialized here.
* Must not be NULL.
* @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to
* do some early early PHY hardware init.
* Can be NULL, if not required.
* @init: Initialize the PHY.
* Must not be NULL.
* @exit: Shutdown the PHY.
* Can be NULL, if not required.
*
* @phy_read: Read from a PHY register.
* Must not be NULL.
* @phy_write: Write to a PHY register.
* Must not be NULL.
* @phy_maskset: Maskset a PHY register, taking shortcuts.
* If it is NULL, a generic algorithm is used.
* @radio_read: Read from a Radio register.
* Must not be NULL.
* @radio_write: Write to a Radio register.
* Must not be NULL.
*
* @supports_hwpctl: Returns a boolean whether Hardware Power Control
* is supported or not.
* If NULL, hwpctl is assumed to be never supported.
* @software_rfkill: Turn the radio ON or OFF.
* Possible state values are
* RFKILL_STATE_SOFT_BLOCKED or
* RFKILL_STATE_UNBLOCKED
* Must not be NULL.
* @switch_analog: Turn the Analog on/off.
* Must not be NULL.
* @switch_channel: Switch the radio to another channel.
* Must not be NULL.
* @get_default_chan: Just returns the default channel number.
* Must not be NULL.
* @set_rx_antenna: Set the antenna used for RX.
* Can be NULL, if not supported.
* @interf_mitigation: Switch the Interference Mitigation mode.
* Can be NULL, if not supported.
*
* @recalc_txpower: Recalculate the transmission power parameters.
* This callback has to recalculate the TX power settings,
* but does not need to write them to the hardware, yet.
* Returns enum b43_txpwr_result to indicate whether the hardware
* needs to be adjusted.
* If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower
* will be called later.
* If the parameter "ignore_tssi" is true, the TSSI values should
* be ignored and a recalculation of the power settings should be
* done even if the TSSI values did not change.
* This function may sleep, but should not.
* Must not be NULL.
* @adjust_txpower: Write the previously calculated TX power settings
* (from @recalc_txpower) to the hardware.
* This function may sleep.
* Can be NULL, if (and ONLY if) @recalc_txpower _always_
* returns B43_TXPWR_RES_DONE.
*
* @pwork_15sec: Periodic work. Called every 15 seconds.
* Can be NULL, if not required.
* @pwork_60sec: Periodic work. Called every 60 seconds.
* Can be NULL, if not required.
*/
struct b43_phy_operations {
/* Initialisation */
int (*allocate)(struct b43_wldev *dev);
void (*free)(struct b43_wldev *dev);
void (*prepare_structs)(struct b43_wldev *dev);
int (*prepare_hardware)(struct b43_wldev *dev);
int (*init)(struct b43_wldev *dev);
void (*exit)(struct b43_wldev *dev);
/* Register access */
u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
/* Radio */
bool (*supports_hwpctl)(struct b43_wldev *dev);
void (*software_rfkill)(struct b43_wldev *dev, bool blocked);
void (*switch_analog)(struct b43_wldev *dev, bool on);
int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
unsigned int (*get_default_chan)(struct b43_wldev *dev);
void (*set_rx_antenna)(struct b43_wldev *dev, int antenna);
int (*interf_mitigation)(struct b43_wldev *dev,
enum b43_interference_mitigation new_mode);
/* Transmission power adjustment */
enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev,
bool ignore_tssi);
void (*adjust_txpower)(struct b43_wldev *dev);
/* Misc */
void (*pwork_15sec)(struct b43_wldev *dev);
void (*pwork_60sec)(struct b43_wldev *dev);
};
struct b43_phy_a;
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. */
const struct b43_phy_operations *ops;
/* Most hardware context information is stored in the standard-
* specific data structures pointed to by the pointers below.
* Only one of them is valid (the currently enabled PHY). */
#ifdef CONFIG_B43_DEBUG
/* No union for debug build to force NULL derefs in buggy code. */
struct {
#else
union {
#endif
/* A-PHY specific information */
struct b43_phy_a *a;
/* G-PHY specific information */
struct b43_phy_g *g;
/* N-PHY specific information */
struct b43_phy_n *n;
/* LP-PHY specific information */
struct b43_phy_lp *lp;
/* HT-PHY specific information */
struct b43_phy_ht *ht;
/* LCN-PHY specific information */
struct b43_phy_lcn *lcn;
/* AC-PHY specific information */
struct b43_phy_ac *ac;
};
/* Band support flags. */
bool supports_2ghz;
bool supports_5ghz;
/* Is GMODE (2 GHz mode) bit enabled? */
bool gmode;
/* After power reset full init has to be performed */
bool do_full_init;
/* Analog Type */
u8 analog;
/* B43_PHYTYPE_ */
u8 type;
/* PHY revision number. */
u8 rev;
/* Count writes since last read */
u8 writes_counter;
/* Radio versioning */
u16 radio_manuf; /* Radio manufacturer */
u16 radio_ver; /* Radio version */
u8 radio_rev; /* Radio revision */
/* Software state of the radio */
bool radio_on;
/* Desired TX power level (in dBm).
* This is set by the user and adjusted in b43_phy_xmitpower(). */
int desired_txpower;
/* Hardware Power Control enabled? */
bool hardware_power_control;
/* The time (in absolute jiffies) when the next TX power output
* check is needed. */
unsigned long next_txpwr_check_time;
/* Current channel */
struct cfg80211_chan_def *chandef;
unsigned int channel;
/* PHY TX errors counter. */
atomic_t txerr_cnt;
#ifdef CONFIG_B43_DEBUG
/* PHY registers locked (w.r.t. firmware) */
bool phy_locked;
/* Radio registers locked (w.r.t. firmware) */
bool radio_locked;
#endif /* B43_DEBUG */
};
/**
* b43_phy_allocate - Allocate PHY structs
* Allocate the PHY data structures, based on the current dev->phy.type
*/
int b43_phy_allocate(struct b43_wldev *dev);
/**
* b43_phy_free - Free PHY structs
*/
void b43_phy_free(struct b43_wldev *dev);
/**
* b43_phy_init - Initialise the PHY
*/
int b43_phy_init(struct b43_wldev *dev);
/**
* b43_phy_exit - Cleanup PHY
*/
void b43_phy_exit(struct b43_wldev *dev);
/**
* b43_has_hardware_pctl - Hardware Power Control supported?
* Returns a boolean, whether hardware power control is supported.
*/
bool b43_has_hardware_pctl(struct b43_wldev *dev);
/**
* b43_phy_read - 16bit PHY register read access
*/
u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
/**
* b43_phy_write - 16bit PHY register write access
*/
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
/**
* b43_phy_copy - copy contents of 16bit PHY register to another
*/
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg);
/**
* b43_phy_mask - Mask a PHY register with a mask
*/
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
/**
* b43_phy_set - OR a PHY register with a bitmap
*/
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
/**
* b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap
*/
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
/**
* b43_radio_read - 16bit Radio register read access
*/
u16 b43_radio_read(struct b43_wldev *dev, u16 reg);
#define b43_radio_read16 b43_radio_read /* DEPRECATED */
/**
* b43_radio_write - 16bit Radio register write access
*/
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value);
#define b43_radio_write16 b43_radio_write /* DEPRECATED */
/**
* b43_radio_mask - Mask a 16bit radio register with a mask
*/
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
/**
* b43_radio_set - OR a 16bit radio register with a bitmap
*/
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
/**
* b43_radio_maskset - Mask and OR a radio register with a mask and bitmap
*/
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
/**
* b43_radio_wait_value - Waits for a given value in masked register read
*/
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
u16 value, int delay, int timeout);
/**
* b43_radio_lock - Lock firmware radio register access
*/
void b43_radio_lock(struct b43_wldev *dev);
/**
* b43_radio_unlock - Unlock firmware radio register access
*/
void b43_radio_unlock(struct b43_wldev *dev);
/**
* b43_phy_lock - Lock firmware PHY register access
*/
void b43_phy_lock(struct b43_wldev *dev);
/**
* b43_phy_unlock - Unlock firmware PHY register access
*/
void b43_phy_unlock(struct b43_wldev *dev);
void b43_phy_put_into_reset(struct b43_wldev *dev);
void b43_phy_take_out_of_reset(struct b43_wldev *dev);
/**
* b43_switch_channel - Switch to another channel
*/
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
/**
* b43_software_rfkill - Turn the radio ON or OFF in software.
*/
void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
/**
* b43_phy_txpower_check - Check TX power output.
*
* Compare the current TX power output to the desired power emission
* and schedule an adjustment in case it mismatches.
*
* @flags: OR'ed enum b43_phy_txpower_check_flags flags.
* See the docs below.
*/
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags);
/**
* enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check()
*
* @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo
* the check now.
* @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average
* TSSI did not change.
*/
enum b43_phy_txpower_check_flags {
B43_TXPWR_IGNORE_TIME = (1 << 0),
B43_TXPWR_IGNORE_TSSI = (1 << 1),
};
struct work_struct;
void b43_phy_txpower_adjust_work(struct work_struct *work);
/**
* b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM.
*
* @shm_offset: The SHM address to read the values from.
*
* Returns the average of the 4 TSSI values, or a negative error code.
*/
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
/**
* b43_phy_switch_analog_generic - Generic PHY operation for switching the Analog.
*
* It does the switching based on the PHY0 core register.
* Do _not_ call this directly. Only use it as a switch_analog callback
* for struct b43_phy_operations.
*/
void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
bool b43_is_40mhz(struct b43_wldev *dev);
void b43_phy_force_clock(struct b43_wldev *dev, bool force);
struct b43_c32 b43_cordic(int theta);
#endif /* LINUX_B43_PHY_COMMON_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
#ifndef LINUX_B43_PHY_G_H_
#define LINUX_B43_PHY_G_H_
/* OFDM PHY registers are defined in the A-PHY header. */
#include "phy_a.h"
/* CCK (B) PHY Registers */
#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
/* Extended G-PHY Registers */
#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
#define B43_PHY_GTABNR_SHIFT 10
#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
#define B43_PHY_RFOVERVAL_LNA 0x7000
#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
#define B43_PHY_RFOVERVAL_PGA 0x0F00
#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
/*** G-PHY table numbers */
#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset);
void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value);
/* Returns the boolean whether "TX Magnification" is enabled. */
#define has_tx_magnification(phy) \
(((phy)->rev >= 2) && \
((phy)->radio_ver == 0x2050) && \
((phy)->radio_rev == 8))
/* Card uses the loopback gain stuff */
#define has_loopback_gain(phy) \
(((phy)->rev > 1) || ((phy)->gmode))
/* Radio Attenuation (RF Attenuation) */
struct b43_rfatt {
u8 att; /* Attenuation value */
bool with_padmix; /* Flag, PAD Mixer enabled. */
};
struct b43_rfatt_list {
/* Attenuation values list */
const struct b43_rfatt *list;
u8 len;
/* Minimum/Maximum attenuation values */
u8 min_val;
u8 max_val;
};
/* Returns true, if the values are the same. */
static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
const struct b43_rfatt *b)
{
return ((a->att == b->att) &&
(a->with_padmix == b->with_padmix));
}
/* Baseband Attenuation */
struct b43_bbatt {
u8 att; /* Attenuation value */
};
struct b43_bbatt_list {
/* Attenuation values list */
const struct b43_bbatt *list;
u8 len;
/* Minimum/Maximum attenuation values */
u8 min_val;
u8 max_val;
};
/* Returns true, if the values are the same. */
static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
const struct b43_bbatt *b)
{
return (a->att == b->att);
}
/* tx_control bits. */
#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
struct b43_txpower_lo_control;
struct b43_phy_g {
/* ACI (adjacent channel interference) flags. */
bool aci_enable;
bool aci_wlan_automatic;
bool aci_hw_rssi;
/* Radio switched on/off */
bool radio_on;
struct {
/* Values saved when turning the radio off.
* They are needed when turning it on again. */
bool valid;
u16 rfover;
u16 rfoverval;
} radio_off_context;
u16 minlowsig[2];
u16 minlowsigpos[2];
/* Pointer to the table used to convert a
* TSSI value to dBm-Q5.2 */
const s8 *tssi2dbm;
/* tssi2dbm is kmalloc()ed. Only used for free()ing. */
bool dyn_tssi_tbl;
/* Target idle TSSI */
int tgt_idle_tssi;
/* Current idle TSSI */
int cur_idle_tssi;
/* The current average TSSI. */
u8 average_tssi;
/* Current TX power level attenuation control values */
struct b43_bbatt bbatt;
struct b43_rfatt rfatt;
u8 tx_control; /* B43_TXCTL_XXX */
/* The calculated attenuation deltas that are used later
* when adjusting the actual power output. */
int bbatt_delta;
int rfatt_delta;
/* LocalOscillator control values. */
struct b43_txpower_lo_control *lo_control;
/* Values from b43_calc_loopback_gain() */
s16 max_lb_gain; /* Maximum Loopback gain in hdB */
s16 trsw_rx_gain; /* TRSW RX gain in hdB */
s16 lna_lod_gain; /* LNA lod */
s16 lna_gain; /* LNA */
s16 pga_gain; /* PGA */
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
* Each value in the stack is laid out as follows:
* bit 0-11: offset
* bit 12-15: register ID
* bit 16-32: value
* register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
*/
#define B43_INTERFSTACK_SIZE 26
u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
/* Saved values from the NRSSI Slope calculation */
s16 nrssi[2];
s32 nrssislope;
/* In memory nrssi lookup table. */
s8 nrssi_lt[64];
u16 lofcal;
u16 initval; //FIXME rename?
/* The device does address auto increment for the OFDM tables.
* We cache the previously used address here and omit the address
* write on the next table access, if possible. */
u16 ofdmtab_addr; /* The address currently set in hardware. */
enum { /* The last data flow direction. */
B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
B43_OFDMTAB_DIRECTION_READ,
B43_OFDMTAB_DIRECTION_WRITE,
} ofdmtab_addr_direction;
};
void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
u16 baseband_attenuation);
void b43_gphy_channel_switch(struct b43_wldev *dev,
unsigned int channel,
bool synthetic_pu_workaround);
u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,
s16 pab0, s16 pab1, s16 pab2);
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_g;
#endif /* LINUX_B43_PHY_G_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
#ifndef B43_PHY_HT_H_
#define B43_PHY_HT_H_
#include "phy_common.h"
#define B43_PHY_HT_BBCFG 0x001 /* BB config */
#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */
#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */
#define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */
#define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */
#define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */
#define B43_PHY_HT_CLASS_CTL 0x0B0 /* Classifier control */
#define B43_PHY_HT_CLASS_CTL_CCK_EN 0x0001 /* CCK enable */
#define B43_PHY_HT_CLASS_CTL_OFDM_EN 0x0002 /* OFDM enable */
#define B43_PHY_HT_CLASS_CTL_WAITED_EN 0x0004 /* Waited enable */
#define B43_PHY_HT_IQLOCAL_CMDGCTL 0x0C2 /* I/Q LO cal command G control */
#define B43_PHY_HT_SAMP_CMD 0x0C3 /* Sample command */
#define B43_PHY_HT_SAMP_CMD_STOP 0x0002 /* Stop */
#define B43_PHY_HT_SAMP_LOOP_CNT 0x0C4 /* Sample loop count */
#define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */
#define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */
#define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */
#define B43_PHY_HT_EST_PWR_C1 0x118
#define B43_PHY_HT_EST_PWR_C2 0x119
#define B43_PHY_HT_EST_PWR_C3 0x11A
#define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */
#define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */
#define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */
#define B43_PHY_HT_BW1 0x1CE
#define B43_PHY_HT_BW2 0x1CF
#define B43_PHY_HT_BW3 0x1D0
#define B43_PHY_HT_BW4 0x1D1
#define B43_PHY_HT_BW5 0x1D2
#define B43_PHY_HT_BW6 0x1D3
#define B43_PHY_HT_TXPCTL_CMD_C1 0x1E7 /* TX power control command */
#define B43_PHY_HT_TXPCTL_CMD_C1_INIT 0x007F /* Init */
#define B43_PHY_HT_TXPCTL_CMD_C1_COEFF 0x2000 /* Power control coefficients */
#define B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN 0x4000 /* Hardware TX power control enable */
#define B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN 0x8000 /* TX power control enable */
#define B43_PHY_HT_TXPCTL_N 0x1E8 /* TX power control N num */
#define B43_PHY_HT_TXPCTL_N_TSSID 0x00FF /* N TSSI delay */
#define B43_PHY_HT_TXPCTL_N_TSSID_SHIFT 0
#define B43_PHY_HT_TXPCTL_N_NPTIL2 0x0700 /* N PT integer log2 */
#define B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT 8
#define B43_PHY_HT_TXPCTL_IDLE_TSSI 0x1E9 /* TX power control idle TSSI */
#define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1 0x003F
#define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT 0
#define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2 0x3F00
#define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT 8
#define B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF 0x8000 /* Raw TSSI offset bin format */
#define B43_PHY_HT_TXPCTL_TARG_PWR 0x1EA /* TX power control target power */
#define B43_PHY_HT_TXPCTL_TARG_PWR_C1 0x00FF /* Power 0 */
#define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8
#define B43_PHY_HT_TX_PCTL_STATUS_C1 0x1ED
#define B43_PHY_HT_TX_PCTL_STATUS_C2 0x1EE
#define B43_PHY_HT_TXPCTL_CMD_C2 0x222
#define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F
#define B43_PHY_HT_RSSI_C1 0x219
#define B43_PHY_HT_RSSI_C2 0x21A
#define B43_PHY_HT_RSSI_C3 0x21B
#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E)
#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E)
#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E)
#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000)
#define B43_PHY_HT_RF_SEQ_MODE_CA_OVER 0x0001 /* Core active override */
#define B43_PHY_HT_RF_SEQ_MODE_TR_OVER 0x0002 /* Trigger override */
#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003)
#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */
#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */
#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */
#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004)
/* Values for the status are the same as for the trigger */
#define B43_PHY_HT_RF_CTL_CMD 0x810
#define B43_PHY_HT_RF_CTL_CMD_FORCE 0x0001
#define B43_PHY_HT_RF_CTL_CMD_CHIP0_PU 0x0002
#define B43_PHY_HT_RF_CTL_INT_C1 B43_PHY_EXTG(0x04c)
#define B43_PHY_HT_RF_CTL_INT_C2 B43_PHY_EXTG(0x06c)
#define B43_PHY_HT_RF_CTL_INT_C3 B43_PHY_EXTG(0x08c)
#define B43_PHY_HT_AFE_C1_OVER B43_PHY_EXTG(0x110)
#define B43_PHY_HT_AFE_C1 B43_PHY_EXTG(0x111)
#define B43_PHY_HT_AFE_C2_OVER B43_PHY_EXTG(0x114)
#define B43_PHY_HT_AFE_C2 B43_PHY_EXTG(0x115)
#define B43_PHY_HT_AFE_C3_OVER B43_PHY_EXTG(0x118)
#define B43_PHY_HT_AFE_C3 B43_PHY_EXTG(0x119)
#define B43_PHY_HT_TXPCTL_CMD_C3 B43_PHY_EXTG(0x164)
#define B43_PHY_HT_TXPCTL_CMD_C3_INIT 0x007F
#define B43_PHY_HT_TXPCTL_IDLE_TSSI2 B43_PHY_EXTG(0x165) /* TX power control idle TSSI */
#define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3 0x003F
#define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT 0
#define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0
#define B43_PHY_HT_TX_PCTL_STATUS_C3 B43_PHY_EXTG(0x169)
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001)
#define B43_PHY_B_BBCFG_RSTCCA 0x4000 /* Reset CCA */
#define B43_PHY_B_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A)
/* Values for PHY registers used on channel switching */
struct b43_phy_ht_channeltab_e_phy {
u16 bw1;
u16 bw2;
u16 bw3;
u16 bw4;
u16 bw5;
u16 bw6;
};
struct b43_phy_ht {
u16 rf_ctl_int_save[3];
bool tx_pwr_ctl;
u8 tx_pwr_idx[3];
s32 bb_mult_save[3];
u8 idle_tssi[3];
};
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_ht;
#endif /* B43_PHY_HT_H_ */

View File

@@ -0,0 +1,855 @@
/*
Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY support
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
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.
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2010 Broadcom Corporation
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
*/
#include <linux/slab.h>
#include "b43.h"
#include "phy_lcn.h"
#include "tables_phy_lcn.h"
#include "main.h"
struct lcn_tx_gains {
u16 gm_gain;
u16 pga_gain;
u16 pad_gain;
u16 dac_gain;
};
struct lcn_tx_iir_filter {
u8 type;
u16 values[16];
};
enum lcn_sense_type {
B43_SENSE_TEMP,
B43_SENSE_VBAT,
};
/**************************************************
* Radio 2064.
**************************************************/
/* wlc_lcnphy_radio_2064_channel_tune_4313 */
static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
{
u16 save[2];
b43_radio_set(dev, 0x09d, 0x4);
b43_radio_write(dev, 0x09e, 0xf);
/* Channel specific values in theory, in practice always the same */
b43_radio_write(dev, 0x02a, 0xb);
b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
b43_radio_maskset(dev, 0x091, ~0x3, 0);
b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
b43_radio_write(dev, 0x06c, 0x80);
save[0] = b43_radio_read(dev, 0x044);
save[1] = b43_radio_read(dev, 0x12b);
b43_radio_set(dev, 0x044, 0x7);
b43_radio_set(dev, 0x12b, 0xe);
/* TODO */
b43_radio_write(dev, 0x040, 0xfb);
b43_radio_write(dev, 0x041, 0x9a);
b43_radio_write(dev, 0x042, 0xa3);
b43_radio_write(dev, 0x043, 0x0c);
/* TODO */
b43_radio_set(dev, 0x044, 0x0c);
udelay(1);
b43_radio_write(dev, 0x044, save[0]);
b43_radio_write(dev, 0x12b, save[1]);
if (dev->phy.rev == 1) {
/* brcmsmac uses outdated 0x3 for 0x038 */
b43_radio_write(dev, 0x038, 0x0);
b43_radio_write(dev, 0x091, 0x7);
}
}
/* wlc_radio_2064_init */
static void b43_radio_2064_init(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_radio_write(dev, 0x09c, 0x0020);
b43_radio_write(dev, 0x105, 0x0008);
} else {
/* TODO */
}
b43_radio_write(dev, 0x032, 0x0062);
b43_radio_write(dev, 0x033, 0x0019);
b43_radio_write(dev, 0x090, 0x0010);
b43_radio_write(dev, 0x010, 0x0000);
if (dev->phy.rev == 1) {
b43_radio_write(dev, 0x060, 0x007f);
b43_radio_write(dev, 0x061, 0x0072);
b43_radio_write(dev, 0x062, 0x007f);
}
b43_radio_write(dev, 0x01d, 0x0002);
b43_radio_write(dev, 0x01e, 0x0006);
b43_phy_write(dev, 0x4ea, 0x4688);
b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
b43_phy_mask(dev, 0x4eb, ~0x01c0);
b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
b43_radio_set(dev, 0x004, 0x40);
b43_radio_set(dev, 0x120, 0x10);
b43_radio_set(dev, 0x078, 0x80);
b43_radio_set(dev, 0x129, 0x2);
b43_radio_set(dev, 0x057, 0x1);
b43_radio_set(dev, 0x05b, 0x2);
/* TODO: wait for some bit to be set */
b43_radio_read(dev, 0x05c);
b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
b43_radio_mask(dev, 0x057, (u16) ~0xff01);
b43_phy_write(dev, 0x933, 0x2d6b);
b43_phy_write(dev, 0x934, 0x2d6b);
b43_phy_write(dev, 0x935, 0x2d6b);
b43_phy_write(dev, 0x936, 0x2d6b);
b43_phy_write(dev, 0x937, 0x016b);
b43_radio_mask(dev, 0x057, (u16) ~0xff02);
b43_radio_write(dev, 0x0c2, 0x006f);
}
/**************************************************
* Various PHY ops
**************************************************/
/* wlc_lcnphy_toggle_afe_pwdn */
static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
{
u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
}
/* wlc_lcnphy_get_pa_gain */
static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
{
return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
}
/* wlc_lcnphy_set_dac_gain */
static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
{
u16 dac_ctrl;
dac_ctrl = b43_phy_read(dev, 0x439);
dac_ctrl = dac_ctrl & 0xc7f;
dac_ctrl = dac_ctrl | (dac_gain << 7);
b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
}
/* wlc_lcnphy_set_bbmult */
static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
{
b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
}
/* wlc_lcnphy_clear_tx_power_offsets */
static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
{
u8 i;
if (1) { /* FIXME */
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
for (i = 0; i < 30; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
}
}
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
for (i = 0; i < 64; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
}
}
/* wlc_lcnphy_rev0_baseband_init */
static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
{
b43_radio_write(dev, 0x11c, 0);
b43_phy_write(dev, 0x43b, 0);
b43_phy_write(dev, 0x43c, 0);
b43_phy_write(dev, 0x44c, 0);
b43_phy_write(dev, 0x4e6, 0);
b43_phy_write(dev, 0x4f9, 0);
b43_phy_write(dev, 0x4b0, 0);
b43_phy_write(dev, 0x938, 0);
b43_phy_write(dev, 0x4b0, 0);
b43_phy_write(dev, 0x44e, 0);
b43_phy_set(dev, 0x567, 0x03);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
; /* TODO */
b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
b43_phy_write(dev, 0x910, 0x1);
}
b43_phy_write(dev, 0x910, 0x1);
b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
}
/* wlc_lcnphy_bu_tweaks */
static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
{
b43_phy_set(dev, 0x805, 0x1);
b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
b43_phy_write(dev, 0x414, 0x1e10);
b43_phy_write(dev, 0x415, 0x0640);
b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
if (dev->dev->bus_sprom->board_rev >= 0x1204)
b43_radio_set(dev, 0x09b, 0xf0);
b43_phy_write(dev, 0x7d6, 0x0902);
b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
if (dev->phy.rev == 1) {
b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
b43_phy_maskset(dev, 0x411, ~0xff, 1);
b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
/* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
b43_phy_maskset(dev, 0x656, ~0xf, 2);
b43_phy_set(dev, 0x44d, 4);
b43_radio_set(dev, 0x0f7, 0x4);
b43_radio_mask(dev, 0x0f1, ~0x3);
b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
b43_radio_set(dev, 0x11f, 0x2);
b43_phy_lcn_clear_tx_power_offsets(dev);
/* TODO: something more? */
}
}
/* wlc_lcnphy_vbat_temp_sense_setup */
static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
enum lcn_sense_type sense_type)
{
u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
u16 auxpga_vmid;
u8 tx_pwr_idx;
u8 i;
u16 save_radio_regs[6][2] = {
{ 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
{ 0x025, 0 }, { 0x112, 0 },
};
u16 save_phy_regs[14][2] = {
{ 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
{ 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
{ 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
{ 0x40d, 0 }, { 0x4a2, 0 },
};
u16 save_radio_4a4;
msleep(1);
/* Save */
for (i = 0; i < 6; i++)
save_radio_regs[i][1] = b43_radio_read(dev,
save_radio_regs[i][0]);
for (i = 0; i < 14; i++)
save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
b43_mac_suspend(dev);
save_radio_4a4 = b43_radio_read(dev, 0x4a4);
/* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
/* Setup */
/* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
b43_radio_set(dev, 0x007, 0x1);
b43_radio_set(dev, 0x0ff, 0x10);
b43_radio_set(dev, 0x11f, 0x4);
b43_phy_mask(dev, 0x503, ~0x1);
b43_phy_mask(dev, 0x503, ~0x4);
b43_phy_mask(dev, 0x4a4, ~0x4000);
b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
b43_phy_mask(dev, 0x4d0, ~0x20);
b43_phy_set(dev, 0x4a5, 0xff);
b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
b43_phy_mask(dev, 0x4a5, ~0x700);
b43_phy_maskset(dev, 0x40d, ~0xff, 64);
b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
b43_phy_mask(dev, 0x4da, ~0x1000);
b43_phy_set(dev, 0x4da, 0x2000);
b43_phy_set(dev, 0x4a6, 0x8000);
b43_radio_write(dev, 0x025, 0xc);
b43_radio_set(dev, 0x005, 0x8);
b43_phy_set(dev, 0x938, 0x4);
b43_phy_set(dev, 0x939, 0x4);
b43_phy_set(dev, 0x4a4, 0x1000);
/* FIXME: don't hardcode */
b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
switch (sense_type) {
case B43_SENSE_TEMP:
b43_phy_set(dev, 0x4d7, 0x8);
b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
auxpga_vmidcourse = 8;
auxpga_vmidfine = 0x4;
auxpga_gain = 2;
b43_radio_set(dev, 0x082, 0x20);
break;
case B43_SENSE_VBAT:
b43_phy_set(dev, 0x4d7, 0x8);
b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
auxpga_vmidcourse = 7;
auxpga_vmidfine = 0xa;
auxpga_gain = 2;
break;
}
auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
b43_phy_set(dev, 0x4d8, 0x1);
b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
b43_phy_set(dev, 0x4d8, 0x2);
b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
b43_phy_set(dev, 0x4d0, 0x20);
b43_radio_write(dev, 0x112, 0x6);
b43_dummy_transmission(dev, true, false);
/* Wait if not done */
if (!(b43_phy_read(dev, 0x476) & 0x8000))
udelay(10);
/* Restore */
for (i = 0; i < 6; i++)
b43_radio_write(dev, save_radio_regs[i][0],
save_radio_regs[i][1]);
for (i = 0; i < 14; i++)
b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
/* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
b43_radio_write(dev, 0x4a4, save_radio_4a4);
b43_mac_enable(dev);
msleep(1);
}
static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
u8 filter_type)
{
int i, j;
u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
0x931, 0x932 };
/* Table is from brcmsmac, values for type 25 were outdated, probably
* others need updating too */
struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
{ 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
1582, 64, 128, 64 } },
{ 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
1863, 93, 167, 93 } },
{ 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
778, 1582, 64, 128, 64 } },
{ 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
754, 1760, 170, 340, 170 } },
{ 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
767, 1760, 256, 185, 256 } },
{ 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
767, 1760, 256, 273, 256 } },
{ 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
767, 1760, 256, 352, 256 } },
{ 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
767, 1760, 128, 233, 128 } },
{ 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
1760, 256, 1881, 256 } },
{ 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
1760, 262, 1878, 262 } },
/* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
* 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
{ 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
1864, 128, 384, 288 } },
{ 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
613, 1864, 128, 384, 288 } },
{ 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
754, 1760, 170, 340, 170 } },
};
for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
if (tx_iir_filters_cck[i].type == filter_type) {
for (j = 0; j < 16; j++)
b43_phy_write(dev, phy_regs[j],
tx_iir_filters_cck[i].values[j]);
return true;
}
}
return false;
}
static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
u8 filter_type)
{
int i, j;
u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
0x90d, 0x90e };
struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
{ 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
{ 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
0xFE2B, 212, 0xFFCE, 212 } },
{ 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
0xFEF2, 128, 0xFFE2, 128 } },
};
for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
if (tx_iir_filters_ofdm[i].type == filter_type) {
for (j = 0; j < 16; j++)
b43_phy_write(dev, phy_regs[j],
tx_iir_filters_ofdm[i].values[j]);
return true;
}
}
return false;
}
/* wlc_lcnphy_set_tx_gain_override */
static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
{
b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
}
/* wlc_lcnphy_set_tx_gain */
static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
struct lcn_tx_gains *target_gains)
{
u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
b43_phy_write(dev, 0x4b5,
(target_gains->gm_gain | (target_gains->pga_gain << 8)));
b43_phy_maskset(dev, 0x4fb, ~0x7fff,
(target_gains->pad_gain | (pa_gain << 8)));
b43_phy_write(dev, 0x4fc,
(target_gains->gm_gain | (target_gains->pga_gain << 8)));
b43_phy_maskset(dev, 0x4fd, ~0x7fff,
(target_gains->pad_gain | (pa_gain << 8)));
b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
b43_phy_lcn_set_tx_gain_override(dev, true);
}
/* wlc_lcnphy_tx_pwr_ctrl_init */
static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
{
struct lcn_tx_gains tx_gains;
u8 bbmult;
b43_mac_suspend(dev);
if (!dev->phy.lcn->hw_pwr_ctl_capable) {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
tx_gains.gm_gain = 4;
tx_gains.pga_gain = 12;
tx_gains.pad_gain = 12;
tx_gains.dac_gain = 0;
bbmult = 150;
} else {
tx_gains.gm_gain = 7;
tx_gains.pga_gain = 15;
tx_gains.pad_gain = 14;
tx_gains.dac_gain = 0;
bbmult = 150;
}
b43_phy_lcn_set_tx_gain(dev, &tx_gains);
b43_phy_lcn_set_bbmult(dev, bbmult);
b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
} else {
b43err(dev->wl, "TX power control not supported for this HW\n");
}
b43_mac_enable(dev);
}
/* wlc_lcnphy_txrx_spur_avoidance_mode */
static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
bool enable)
{
if (enable) {
b43_phy_write(dev, 0x942, 0x7);
b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
b43_phy_write(dev, 0x44a, 0x084);
b43_phy_write(dev, 0x44a, 0x080);
b43_phy_write(dev, 0x6d3, 0x2222);
b43_phy_write(dev, 0x6d3, 0x2220);
} else {
b43_phy_write(dev, 0x942, 0x0);
b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
}
b43_mac_switch_freq(dev, enable);
}
/**************************************************
* Channel switching ops.
**************************************************/
/* wlc_lcnphy_set_chanspec_tweaks */
static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
{
struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
channel == 9 || channel == 10 || channel == 11 || channel == 12) {
bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
b43_phy_write(dev, 0x942, 0);
b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
b43_phy_write(dev, 0x425, 0x5907);
} else {
bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
b43_phy_write(dev, 0x942, 0);
b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
b43_phy_write(dev, 0x425, 0x590a);
}
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
}
/* wlc_phy_chanspec_set_lcnphy */
static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
{
static const u16 sfo_cfg[14][2] = {
{965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
{975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
{985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
};
b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
b43_radio_2064_channel_setup(dev);
mdelay(1);
b43_phy_lcn_afe_set_unset(dev);
b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
if (channel->hw_value == 14) {
b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
} else {
b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
/* brcmsmac uses filter_type 2, we follow wl with 25 */
b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
}
/* brcmsmac uses filter_type 2, we follow wl with 0 */
b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
return 0;
}
/**************************************************
* Basic PHY ops.
**************************************************/
static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_lcn *phy_lcn;
phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
if (!phy_lcn)
return -ENOMEM;
dev->phy.lcn = phy_lcn;
return 0;
}
static void b43_phy_lcn_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_lcn *phy_lcn = phy->lcn;
kfree(phy_lcn);
phy->lcn = NULL;
}
static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_lcn *phy_lcn = phy->lcn;
memset(phy_lcn, 0, sizeof(*phy_lcn));
}
/* wlc_phy_init_lcnphy */
static int b43_phy_lcn_op_init(struct b43_wldev *dev)
{
struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
b43_phy_set(dev, 0x44a, 0x80);
b43_phy_mask(dev, 0x44a, 0x7f);
b43_phy_set(dev, 0x6d1, 0x80);
b43_phy_write(dev, 0x6d0, 0x7);
b43_phy_lcn_afe_set_unset(dev);
b43_phy_write(dev, 0x60a, 0xa0);
b43_phy_write(dev, 0x46a, 0x19);
b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
b43_phy_lcn_tables_init(dev);
b43_phy_lcn_rev0_baseband_init(dev);
b43_phy_lcn_bu_tweaks(dev);
if (dev->phy.radio_ver == 0x2064)
b43_radio_2064_init(dev);
else
B43_WARN_ON(1);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
b43_phy_lcn_tx_pwr_ctl_init(dev);
b43_switch_channel(dev, dev->phy.channel);
bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
/* TODO */
b43_phy_set(dev, 0x448, 0x4000);
udelay(100);
b43_phy_mask(dev, 0x448, ~0x4000);
/* TODO */
return 0;
}
static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
b43err(dev->wl, "MAC not suspended\n");
if (blocked) {
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
} else {
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
}
}
static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
{
if (on) {
b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
} else {
b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
}
}
static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
enum nl80211_channel_type channel_type =
cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
return -EINVAL;
} else {
return -EINVAL;
}
return b43_phy_lcn_set_channel(dev, channel, channel_type);
}
static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
return 1;
return 36;
}
static enum b43_txpwr_result
b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
{
return B43_TXPWR_RES_DONE;
}
static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
{
}
/**************************************************
* R/W ops.
**************************************************/
static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
u16 set)
{
b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA,
(b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
}
static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* LCN-PHY needs 0x200 for read access */
reg |= 0x200;
b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
u16 value)
{
b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
}
/**************************************************
* 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_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,
};

View File

@@ -0,0 +1,31 @@
#ifndef B43_PHY_LCN_H_
#define B43_PHY_LCN_H_
#include "phy_common.h"
#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B)
#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C)
#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
#define B43_PHY_LCN_TABLE_ADDR B43_PHY_OFDM(0x055) /* Table address */
#define B43_PHY_LCN_TABLE_DATALO B43_PHY_OFDM(0x056) /* Table data low */
#define B43_PHY_LCN_TABLE_DATAHI B43_PHY_OFDM(0x057) /* Table data high */
#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1)
#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7)
#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9)
#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA)
struct b43_phy_lcn {
bool hw_pwr_ctl;
bool hw_pwr_ctl_capable;
u8 tx_pwr_curr_idx;
};
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lcn;
#endif /* B43_PHY_LCN_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,912 @@
#ifndef LINUX_B43_PHY_LP_H_
#define LINUX_B43_PHY_LP_H_
/* Definitions for the LP-PHY */
/* The CCK PHY register range. */
#define B43_LPPHY_B_VERSION B43_PHY_CCK(0x00) /* B PHY version */
#define B43_LPPHY_B_BBCONFIG B43_PHY_CCK(0x01) /* B PHY BBConfig */
#define B43_LPPHY_B_RX_STAT0 B43_PHY_CCK(0x04) /* B PHY RX Status0 */
#define B43_LPPHY_B_RX_STAT1 B43_PHY_CCK(0x05) /* B PHY RX Status1 */
#define B43_LPPHY_B_CRS_THRESH B43_PHY_CCK(0x06) /* B PHY CRS Thresh */
#define B43_LPPHY_B_TXERROR B43_PHY_CCK(0x07) /* B PHY TxError */
#define B43_LPPHY_B_CHANNEL B43_PHY_CCK(0x08) /* B PHY Channel */
#define B43_LPPHY_B_WORKAROUND B43_PHY_CCK(0x09) /* B PHY workaround */
#define B43_LPPHY_B_TEST B43_PHY_CCK(0x0A) /* B PHY Test */
#define B43_LPPHY_B_FOURWIRE_ADDR B43_PHY_CCK(0x0B) /* B PHY Fourwire Address */
#define B43_LPPHY_B_FOURWIRE_DATA_HI B43_PHY_CCK(0x0C) /* B PHY Fourwire Data Hi */
#define B43_LPPHY_B_FOURWIRE_DATA_LO B43_PHY_CCK(0x0D) /* B PHY Fourwire Data Lo */
#define B43_LPPHY_B_BIST_STAT B43_PHY_CCK(0x0E) /* B PHY Bist Status */
#define B43_LPPHY_PA_RAMP_TX_TO B43_PHY_CCK(0x10) /* PA Ramp TX Timeout */
#define B43_LPPHY_RF_SYNTH_DC_TIMER B43_PHY_CCK(0x11) /* RF Synth DC Timer */
#define B43_LPPHY_PA_RAMP_TX_TIME_IN B43_PHY_CCK(0x12) /* PA ramp TX Time in */
#define B43_LPPHY_RX_FILTER_TIME_IN B43_PHY_CCK(0x13) /* RX Filter Time in */
#define B43_LPPHY_PLL_COEFF_S B43_PHY_CCK(0x18) /* PLL Coefficient(s) */
#define B43_LPPHY_PLL_OUT B43_PHY_CCK(0x19) /* PLL Out */
#define B43_LPPHY_RSSI_THRES B43_PHY_CCK(0x20) /* RSSI Threshold */
#define B43_LPPHY_IQ_THRES_HH B43_PHY_CCK(0x21) /* IQ Threshold HH */
#define B43_LPPHY_IQ_THRES_H B43_PHY_CCK(0x22) /* IQ Threshold H */
#define B43_LPPHY_IQ_THRES_L B43_PHY_CCK(0x23) /* IQ Threshold L */
#define B43_LPPHY_IQ_THRES_LL B43_PHY_CCK(0x24) /* IQ Threshold LL */
#define B43_LPPHY_AGC_GAIN B43_PHY_CCK(0x25) /* AGC Gain */
#define B43_LPPHY_LNA_GAIN_RANGE B43_PHY_CCK(0x26) /* LNA Gain Range */
#define B43_LPPHY_JSSI B43_PHY_CCK(0x27) /* JSSI */
#define B43_LPPHY_TSSI_CTL B43_PHY_CCK(0x28) /* TSSI Control */
#define B43_LPPHY_TSSI B43_PHY_CCK(0x29) /* TSSI */
#define B43_LPPHY_TR_LOSS B43_PHY_CCK(0x2A) /* TR Loss */
#define B43_LPPHY_LO_LEAKAGE B43_PHY_CCK(0x2B) /* LO Leakage */
#define B43_LPPHY_LO_RSSIACC B43_PHY_CCK(0x2C) /* LO RSSIAcc */
#define B43_LPPHY_LO_IQ_MAG_ACC B43_PHY_CCK(0x2D) /* LO IQ Mag Acc */
#define B43_LPPHY_TX_DCOFFSET1 B43_PHY_CCK(0x2E) /* TX DCOffset1 */
#define B43_LPPHY_TX_DCOFFSET2 B43_PHY_CCK(0x2F) /* TX DCOffset2 */
#define B43_LPPHY_SYNCPEAKCNT B43_PHY_CCK(0x30) /* SyncPeakCnt */
#define B43_LPPHY_SYNCFREQ B43_PHY_CCK(0x31) /* SyncFreq */
#define B43_LPPHY_SYNCDIVERSITYCTL B43_PHY_CCK(0x32) /* SyncDiversityControl */
#define B43_LPPHY_PEAKENERGYL B43_PHY_CCK(0x33) /* PeakEnergyL */
#define B43_LPPHY_PEAKENERGYH B43_PHY_CCK(0x34) /* PeakEnergyH */
#define B43_LPPHY_SYNCCTL B43_PHY_CCK(0x35) /* SyncControl */
#define B43_LPPHY_DSSSSTEP B43_PHY_CCK(0x38) /* DsssStep */
#define B43_LPPHY_DSSSWARMUP B43_PHY_CCK(0x39) /* DsssWarmup */
#define B43_LPPHY_DSSSSIGPOW B43_PHY_CCK(0x3D) /* DsssSigPow */
#define B43_LPPHY_SFDDETECTBLOCKTIME B43_PHY_CCK(0x40) /* SfdDetectBlockTIme */
#define B43_LPPHY_SFDTO B43_PHY_CCK(0x41) /* SFDTimeOut */
#define B43_LPPHY_SFDCTL B43_PHY_CCK(0x42) /* SFDControl */
#define B43_LPPHY_RXDBG B43_PHY_CCK(0x43) /* rxDebug */
#define B43_LPPHY_RX_DELAYCOMP B43_PHY_CCK(0x44) /* RX DelayComp */
#define B43_LPPHY_CRSDROPOUTTO B43_PHY_CCK(0x45) /* CRSDropoutTimeout */
#define B43_LPPHY_PSEUDOSHORTTO B43_PHY_CCK(0x46) /* PseudoShortTimeout */
#define B43_LPPHY_PR3931 B43_PHY_CCK(0x47) /* PR3931 */
#define B43_LPPHY_DSSSCOEFF1 B43_PHY_CCK(0x48) /* DSSSCoeff1 */
#define B43_LPPHY_DSSSCOEFF2 B43_PHY_CCK(0x49) /* DSSSCoeff2 */
#define B43_LPPHY_CCKCOEFF1 B43_PHY_CCK(0x4A) /* CCKCoeff1 */
#define B43_LPPHY_CCKCOEFF2 B43_PHY_CCK(0x4B) /* CCKCoeff2 */
#define B43_LPPHY_TRCORR B43_PHY_CCK(0x4C) /* TRCorr */
#define B43_LPPHY_ANGLESCALE B43_PHY_CCK(0x4D) /* AngleScale */
#define B43_LPPHY_OPTIONALMODES2 B43_PHY_CCK(0x4F) /* OptionalModes2 */
#define B43_LPPHY_CCKLMSSTEPSIZE B43_PHY_CCK(0x50) /* CCKLMSStepSize */
#define B43_LPPHY_DFEBYPASS B43_PHY_CCK(0x51) /* DFEBypass */
#define B43_LPPHY_CCKSTARTDELAYLONG B43_PHY_CCK(0x52) /* CCKStartDelayLong */
#define B43_LPPHY_CCKSTARTDELAYSHORT B43_PHY_CCK(0x53) /* CCKStartDelayShort */
#define B43_LPPHY_PPROCCHDELAY B43_PHY_CCK(0x54) /* PprocChDelay */
#define B43_LPPHY_PPROCONOFF B43_PHY_CCK(0x55) /* PProcOnOff */
#define B43_LPPHY_LNAGAINTWOBIT10 B43_PHY_CCK(0x5B) /* LNAGainTwoBit10 */
#define B43_LPPHY_LNAGAINTWOBIT32 B43_PHY_CCK(0x5C) /* LNAGainTwoBit32 */
#define B43_LPPHY_OPTIONALMODES B43_PHY_CCK(0x5D) /* OptionalModes */
#define B43_LPPHY_B_RX_STAT2 B43_PHY_CCK(0x5E) /* B PHY RX Status2 */
#define B43_LPPHY_B_RX_STAT3 B43_PHY_CCK(0x5F) /* B PHY RX Status3 */
#define B43_LPPHY_PWDNDACDELAY B43_PHY_CCK(0x63) /* pwdnDacDelay */
#define B43_LPPHY_FINEDIGIGAIN_CTL B43_PHY_CCK(0x67) /* FineDigiGain Control */
#define B43_LPPHY_LG2GAINTBLLNA8 B43_PHY_CCK(0x68) /* Lg2GainTblLNA8 */
#define B43_LPPHY_LG2GAINTBLLNA28 B43_PHY_CCK(0x69) /* Lg2GainTblLNA28 */
#define B43_LPPHY_GAINTBLLNATRSW B43_PHY_CCK(0x6A) /* GainTblLNATrSw */
#define B43_LPPHY_PEAKENERGY B43_PHY_CCK(0x6B) /* PeakEnergy */
#define B43_LPPHY_LG2INITGAIN B43_PHY_CCK(0x6C) /* lg2InitGain */
#define B43_LPPHY_BLANKCOUNTLNAPGA B43_PHY_CCK(0x6D) /* BlankCountLnaPga */
#define B43_LPPHY_LNAGAINTWOBIT54 B43_PHY_CCK(0x6E) /* LNAGainTwoBit54 */
#define B43_LPPHY_LNAGAINTWOBIT76 B43_PHY_CCK(0x6F) /* LNAGainTwoBit76 */
#define B43_LPPHY_JSSICTL B43_PHY_CCK(0x70) /* JSSIControl */
#define B43_LPPHY_LG2GAINTBLLNA44 B43_PHY_CCK(0x71) /* Lg2GainTblLNA44 */
#define B43_LPPHY_LG2GAINTBLLNA62 B43_PHY_CCK(0x72) /* Lg2GainTblLNA62 */
/* The OFDM PHY register range. */
#define B43_LPPHY_VERSION B43_PHY_OFDM(0x00) /* Version */
#define B43_LPPHY_BBCONFIG B43_PHY_OFDM(0x01) /* BBConfig */
#define B43_LPPHY_RX_STAT0 B43_PHY_OFDM(0x04) /* RX Status0 */
#define B43_LPPHY_RX_STAT1 B43_PHY_OFDM(0x05) /* RX Status1 */
#define B43_LPPHY_TX_ERROR B43_PHY_OFDM(0x07) /* TX Error */
#define B43_LPPHY_CHANNEL B43_PHY_OFDM(0x08) /* Channel */
#define B43_LPPHY_WORKAROUND B43_PHY_OFDM(0x09) /* workaround */
#define B43_LPPHY_FOURWIRE_ADDR B43_PHY_OFDM(0x0B) /* Fourwire Address */
#define B43_LPPHY_FOURWIREDATAHI B43_PHY_OFDM(0x0C) /* FourwireDataHi */
#define B43_LPPHY_FOURWIREDATALO B43_PHY_OFDM(0x0D) /* FourwireDataLo */
#define B43_LPPHY_BISTSTAT0 B43_PHY_OFDM(0x0E) /* BistStatus0 */
#define B43_LPPHY_BISTSTAT1 B43_PHY_OFDM(0x0F) /* BistStatus1 */
#define B43_LPPHY_CRSGAIN_CTL B43_PHY_OFDM(0x10) /* crsgain Control */
#define B43_LPPHY_OFDMPWR_THRESH0 B43_PHY_OFDM(0x11) /* ofdmPower Thresh0 */
#define B43_LPPHY_OFDMPWR_THRESH1 B43_PHY_OFDM(0x12) /* ofdmPower Thresh1 */
#define B43_LPPHY_OFDMPWR_THRESH2 B43_PHY_OFDM(0x13) /* ofdmPower Thresh2 */
#define B43_LPPHY_DSSSPWR_THRESH0 B43_PHY_OFDM(0x14) /* dsssPower Thresh0 */
#define B43_LPPHY_DSSSPWR_THRESH1 B43_PHY_OFDM(0x15) /* dsssPower Thresh1 */
#define B43_LPPHY_MINPWR_LEVEL B43_PHY_OFDM(0x16) /* MinPower Level */
#define B43_LPPHY_OFDMSYNCTHRESH0 B43_PHY_OFDM(0x17) /* ofdmSyncThresh0 */
#define B43_LPPHY_OFDMSYNCTHRESH1 B43_PHY_OFDM(0x18) /* ofdmSyncThresh1 */
#define B43_LPPHY_FINEFREQEST B43_PHY_OFDM(0x19) /* FineFreqEst */
#define B43_LPPHY_IDLEAFTERPKTRXTO B43_PHY_OFDM(0x1A) /* IDLEafterPktRXTimeout */
#define B43_LPPHY_LTRN_CTL B43_PHY_OFDM(0x1B) /* LTRN Control */
#define B43_LPPHY_DCOFFSETTRANSIENT B43_PHY_OFDM(0x1C) /* DCOffsetTransient */
#define B43_LPPHY_PREAMBLEINTO B43_PHY_OFDM(0x1D) /* PreambleInTimeout */
#define B43_LPPHY_PREAMBLECONFIRMTO B43_PHY_OFDM(0x1E) /* PreambleConfirmTimeout */
#define B43_LPPHY_CLIPTHRESH B43_PHY_OFDM(0x1F) /* ClipThresh */
#define B43_LPPHY_CLIPCTRTHRESH B43_PHY_OFDM(0x20) /* ClipCtrThresh */
#define B43_LPPHY_OFDMSYNCTIMER_CTL B43_PHY_OFDM(0x21) /* ofdmSyncTimer Control */
#define B43_LPPHY_WAITFORPHYSELTO B43_PHY_OFDM(0x22) /* WaitforPHYSelTimeout */
#define B43_LPPHY_HIGAINDB B43_PHY_OFDM(0x23) /* HiGainDB */
#define B43_LPPHY_LOWGAINDB B43_PHY_OFDM(0x24) /* LowGainDB */
#define B43_LPPHY_VERYLOWGAINDB B43_PHY_OFDM(0x25) /* VeryLowGainDB */
#define B43_LPPHY_GAINMISMATCH B43_PHY_OFDM(0x26) /* gainMismatch */
#define B43_LPPHY_GAINDIRECTMISMATCH B43_PHY_OFDM(0x27) /* gaindirectMismatch */
#define B43_LPPHY_PWR_THRESH0 B43_PHY_OFDM(0x28) /* Power Thresh0 */
#define B43_LPPHY_PWR_THRESH1 B43_PHY_OFDM(0x29) /* Power Thresh1 */
#define B43_LPPHY_DETECTOR_DELAY_ADJUST B43_PHY_OFDM(0x2A) /* Detector Delay Adjust */
#define B43_LPPHY_REDUCED_DETECTOR_DELAY B43_PHY_OFDM(0x2B) /* Reduced Detector Delay */
#define B43_LPPHY_DATA_TO B43_PHY_OFDM(0x2C) /* data Timeout */
#define B43_LPPHY_CORRELATOR_DIS_DELAY B43_PHY_OFDM(0x2D) /* correlator Dis Delay */
#define B43_LPPHY_DIVERSITY_GAINBACK B43_PHY_OFDM(0x2E) /* Diversity GainBack */
#define B43_LPPHY_DSSS_CONFIRM_CNT B43_PHY_OFDM(0x2F) /* DSSS Confirm Cnt */
#define B43_LPPHY_DC_BLANK_INT B43_PHY_OFDM(0x30) /* DC Blank Interval */
#define B43_LPPHY_GAIN_MISMATCH_LIMIT B43_PHY_OFDM(0x31) /* gain Mismatch Limit */
#define B43_LPPHY_CRS_ED_THRESH B43_PHY_OFDM(0x32) /* crs ed thresh */
#define B43_LPPHY_PHASE_SHIFT_CTL B43_PHY_OFDM(0x33) /* phase shift Control */
#define B43_LPPHY_INPUT_PWRDB B43_PHY_OFDM(0x34) /* Input PowerDB */
#define B43_LPPHY_OFDM_SYNC_CTL B43_PHY_OFDM(0x35) /* ofdm sync Control */
#define B43_LPPHY_AFE_ADC_CTL_0 B43_PHY_OFDM(0x36) /* Afe ADC Control 0 */
#define B43_LPPHY_AFE_ADC_CTL_1 B43_PHY_OFDM(0x37) /* Afe ADC Control 1 */
#define B43_LPPHY_AFE_ADC_CTL_2 B43_PHY_OFDM(0x38) /* Afe ADC Control 2 */
#define B43_LPPHY_AFE_DAC_CTL B43_PHY_OFDM(0x39) /* Afe DAC Control */
#define B43_LPPHY_AFE_CTL B43_PHY_OFDM(0x3A) /* Afe Control */
#define B43_LPPHY_AFE_CTL_OVR B43_PHY_OFDM(0x3B) /* Afe Control Ovr */
#define B43_LPPHY_AFE_CTL_OVRVAL B43_PHY_OFDM(0x3C) /* Afe Control OvrVal */
#define B43_LPPHY_AFE_RSSI_CTL_0 B43_PHY_OFDM(0x3D) /* Afe RSSI Control 0 */
#define B43_LPPHY_AFE_RSSI_CTL_1 B43_PHY_OFDM(0x3E) /* Afe RSSI Control 1 */
#define B43_LPPHY_AFE_RSSI_SEL B43_PHY_OFDM(0x3F) /* Afe RSSI Sel */
#define B43_LPPHY_RADAR_THRESH B43_PHY_OFDM(0x40) /* Radar Thresh */
#define B43_LPPHY_RADAR_BLANK_INT B43_PHY_OFDM(0x41) /* Radar blank Interval */
#define B43_LPPHY_RADAR_MIN_FM_INT B43_PHY_OFDM(0x42) /* Radar min fm Interval */
#define B43_LPPHY_RADAR_GAIN_TO B43_PHY_OFDM(0x43) /* Radar gain timeout */
#define B43_LPPHY_RADAR_PULSE_TO B43_PHY_OFDM(0x44) /* Radar pulse timeout */
#define B43_LPPHY_RADAR_DETECT_FM_CTL B43_PHY_OFDM(0x45) /* Radar detect FM Control */
#define B43_LPPHY_RADAR_DETECT_EN B43_PHY_OFDM(0x46) /* Radar detect En */
#define B43_LPPHY_RADAR_RD_DATA_REG B43_PHY_OFDM(0x47) /* Radar Rd Data Reg */
#define B43_LPPHY_LP_PHY_CTL B43_PHY_OFDM(0x48) /* LP PHY Control */
#define B43_LPPHY_CLASSIFIER_CTL B43_PHY_OFDM(0x49) /* classifier Control */
#define B43_LPPHY_RESET_CTL B43_PHY_OFDM(0x4A) /* reset Control */
#define B43_LPPHY_CLKEN_CTL B43_PHY_OFDM(0x4B) /* ClkEn Control */
#define B43_LPPHY_RF_OVERRIDE_0 B43_PHY_OFDM(0x4C) /* RF Override 0 */
#define B43_LPPHY_RF_OVERRIDE_VAL_0 B43_PHY_OFDM(0x4D) /* RF Override Val 0 */
#define B43_LPPHY_TR_LOOKUP_1 B43_PHY_OFDM(0x4E) /* TR Lookup 1 */
#define B43_LPPHY_TR_LOOKUP_2 B43_PHY_OFDM(0x4F) /* TR Lookup 2 */
#define B43_LPPHY_RSSISELLOOKUP1 B43_PHY_OFDM(0x50) /* RssiSelLookup1 */
#define B43_LPPHY_IQLO_CAL_CMD B43_PHY_OFDM(0x51) /* iqlo Cal Cmd */
#define B43_LPPHY_IQLO_CAL_CMD_N_NUM B43_PHY_OFDM(0x52) /* iqlo Cal Cmd N num */
#define B43_LPPHY_IQLO_CAL_CMD_G_CTL B43_PHY_OFDM(0x53) /* iqlo Cal Cmd G control */
#define B43_LPPHY_MACINT_DBG_REGISTER B43_PHY_OFDM(0x54) /* macint Debug Register */
#define B43_LPPHY_TABLE_ADDR B43_PHY_OFDM(0x55) /* Table Address */
#define B43_LPPHY_TABLEDATALO B43_PHY_OFDM(0x56) /* TabledataLo */
#define B43_LPPHY_TABLEDATAHI B43_PHY_OFDM(0x57) /* TabledataHi */
#define B43_LPPHY_PHY_CRS_ENABLE_ADDR B43_PHY_OFDM(0x58) /* phy CRS Enable Address */
#define B43_LPPHY_IDLETIME_CTL B43_PHY_OFDM(0x59) /* Idletime Control */
#define B43_LPPHY_IDLETIME_CRS_ON_LO B43_PHY_OFDM(0x5A) /* Idletime CRS On Lo */
#define B43_LPPHY_IDLETIME_CRS_ON_HI B43_PHY_OFDM(0x5B) /* Idletime CRS On Hi */
#define B43_LPPHY_IDLETIME_MEAS_TIME_LO B43_PHY_OFDM(0x5C) /* Idletime Meas Time Lo */
#define B43_LPPHY_IDLETIME_MEAS_TIME_HI B43_PHY_OFDM(0x5D) /* Idletime Meas Time Hi */
#define B43_LPPHY_RESET_LEN_OFDM_TX_ADDR B43_PHY_OFDM(0x5E) /* Reset len Ofdm TX Address */
#define B43_LPPHY_RESET_LEN_OFDM_RX_ADDR B43_PHY_OFDM(0x5F) /* Reset len Ofdm RX Address */
#define B43_LPPHY_REG_CRS_ENABLE B43_PHY_OFDM(0x60) /* reg crs enable */
#define B43_LPPHY_PLCP_TMT_STR0_CTR_MIN B43_PHY_OFDM(0x61) /* PLCP Tmt Str0 Ctr Min */
#define B43_LPPHY_PKT_FSM_RESET_LEN_VAL B43_PHY_OFDM(0x62) /* Pkt fsm Reset Len Value */
#define B43_LPPHY_READSYM2RESET_CTL B43_PHY_OFDM(0x63) /* readsym2reset Control */
#define B43_LPPHY_DC_FILTER_DELAY1 B43_PHY_OFDM(0x64) /* Dc filter delay1 */
#define B43_LPPHY_PACKET_RX_ACTIVE_TO B43_PHY_OFDM(0x65) /* packet rx Active timeout */
#define B43_LPPHY_ED_TOVAL B43_PHY_OFDM(0x66) /* ed timeoutValue */
#define B43_LPPHY_HOLD_CRS_ON_VAL B43_PHY_OFDM(0x67) /* hold CRS On Value */
#define B43_LPPHY_OFDM_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x69) /* ofdm tx phy CRS Delay Value */
#define B43_LPPHY_CCK_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x6A) /* cck tx phy CRS Delay Value */
#define B43_LPPHY_ED_ON_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6B) /* Ed on confirm Timer Value */
#define B43_LPPHY_ED_OFFSET_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6C) /* Ed offset confirm Timer Value */
#define B43_LPPHY_PHY_CRS_OFFSET_TIMER_VAL B43_PHY_OFDM(0x6D) /* phy CRS offset Timer Value */
#define B43_LPPHY_ADC_COMPENSATION_CTL B43_PHY_OFDM(0x70) /* ADC Compensation Control */
#define B43_LPPHY_LOG2_RBPSK_ADDR B43_PHY_OFDM(0x71) /* log2 RBPSK Address */
#define B43_LPPHY_LOG2_RQPSK_ADDR B43_PHY_OFDM(0x72) /* log2 RQPSK Address */
#define B43_LPPHY_LOG2_R16QAM_ADDR B43_PHY_OFDM(0x73) /* log2 R16QAM Address */
#define B43_LPPHY_LOG2_R64QAM_ADDR B43_PHY_OFDM(0x74) /* log2 R64QAM Address */
#define B43_LPPHY_OFFSET_BPSK_ADDR B43_PHY_OFDM(0x75) /* offset BPSK Address */
#define B43_LPPHY_OFFSET_QPSK_ADDR B43_PHY_OFDM(0x76) /* offset QPSK Address */
#define B43_LPPHY_OFFSET_16QAM_ADDR B43_PHY_OFDM(0x77) /* offset 16QAM Address */
#define B43_LPPHY_OFFSET_64QAM_ADDR B43_PHY_OFDM(0x78) /* offset 64QAM Address */
#define B43_LPPHY_ALPHA1 B43_PHY_OFDM(0x79) /* Alpha1 */
#define B43_LPPHY_ALPHA2 B43_PHY_OFDM(0x7A) /* Alpha2 */
#define B43_LPPHY_BETA1 B43_PHY_OFDM(0x7B) /* Beta1 */
#define B43_LPPHY_BETA2 B43_PHY_OFDM(0x7C) /* Beta2 */
#define B43_LPPHY_LOOP_NUM_ADDR B43_PHY_OFDM(0x7D) /* Loop Num Address */
#define B43_LPPHY_STR_COLLMAX_SMPL_ADDR B43_PHY_OFDM(0x7E) /* Str Collmax Sample Address */
#define B43_LPPHY_MAX_SMPL_COARSE_FINE_ADDR B43_PHY_OFDM(0x7F) /* Max Sample Coarse/Fine Address */
#define B43_LPPHY_MAX_SMPL_COARSE_STR0CTR_ADDR B43_PHY_OFDM(0x80) /* Max Sample Coarse/Str0Ctr Address */
#define B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR B43_PHY_OFDM(0x81) /* IQ Enable Wait Time Address */
#define B43_LPPHY_IQ_NUM_SMPLS_ADDR B43_PHY_OFDM(0x82) /* IQ Num Samples Address */
#define B43_LPPHY_IQ_ACC_HI_ADDR B43_PHY_OFDM(0x83) /* IQ Acc Hi Address */
#define B43_LPPHY_IQ_ACC_LO_ADDR B43_PHY_OFDM(0x84) /* IQ Acc Lo Address */
#define B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x85) /* IQ I PWR Acc Hi Address */
#define B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x86) /* IQ I PWR Acc Lo Address */
#define B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x87) /* IQ Q PWR Acc Hi Address */
#define B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x88) /* IQ Q PWR Acc Lo Address */
#define B43_LPPHY_MAXNUMSTEPS B43_PHY_OFDM(0x89) /* MaxNumsteps */
#define B43_LPPHY_ROTORPHASE_ADDR B43_PHY_OFDM(0x8A) /* RotorPhase Address */
#define B43_LPPHY_ADVANCEDRETARDROTOR_ADDR B43_PHY_OFDM(0x8B) /* AdvancedRetardRotor Address */
#define B43_LPPHY_RSSIADCDELAY_CTL_ADDR B43_PHY_OFDM(0x8D) /* rssiAdcdelay Control Address */
#define B43_LPPHY_TSSISTAT_ADDR B43_PHY_OFDM(0x8E) /* tssiStatus Address */
#define B43_LPPHY_TEMPSENSESTAT_ADDR B43_PHY_OFDM(0x8F) /* tempsenseStatus Address */
#define B43_LPPHY_TEMPSENSE_CTL_ADDR B43_PHY_OFDM(0x90) /* tempsense Control Address */
#define B43_LPPHY_WRSSISTAT_ADDR B43_PHY_OFDM(0x91) /* wrssistatus Address */
#define B43_LPPHY_MUFACTORADDR B43_PHY_OFDM(0x92) /* mufactoraddr */
#define B43_LPPHY_SCRAMSTATE_ADDR B43_PHY_OFDM(0x93) /* scramstate Address */
#define B43_LPPHY_TXHOLDOFFADDR B43_PHY_OFDM(0x94) /* txholdoffaddr */
#define B43_LPPHY_PKTGAINVAL_ADDR B43_PHY_OFDM(0x95) /* pktgainval Address */
#define B43_LPPHY_COARSEESTIM_ADDR B43_PHY_OFDM(0x96) /* Coarseestim Address */
#define B43_LPPHY_STATE_TRANSITION_ADDR B43_PHY_OFDM(0x97) /* state Transition Address */
#define B43_LPPHY_TRN_OFFSET_ADDR B43_PHY_OFDM(0x98) /* TRN offset Address */
#define B43_LPPHY_NUM_ROTOR_ADDR B43_PHY_OFDM(0x99) /* Num Rotor Address */
#define B43_LPPHY_VITERBI_OFFSET_ADDR B43_PHY_OFDM(0x9A) /* Viterbi Offset Address */
#define B43_LPPHY_SMPL_COLLECT_WAIT_ADDR B43_PHY_OFDM(0x9B) /* Sample collect wait Address */
#define B43_LPPHY_A_PHY_CTL_ADDR B43_PHY_OFDM(0x9C) /* A PHY Control Address */
#define B43_LPPHY_NUM_PASS_THROUGH_ADDR B43_PHY_OFDM(0x9D) /* Num Pass Through Address */
#define B43_LPPHY_RX_COMP_COEFF_S B43_PHY_OFDM(0x9E) /* RX Comp coefficient(s) */
#define B43_LPPHY_CPAROTATEVAL B43_PHY_OFDM(0x9F) /* cpaRotateValue */
#define B43_LPPHY_SMPL_PLAY_COUNT B43_PHY_OFDM(0xA0) /* Sample play count */
#define B43_LPPHY_SMPL_PLAY_BUFFER_CTL B43_PHY_OFDM(0xA1) /* Sample play Buffer Control */
#define B43_LPPHY_FOURWIRE_CTL B43_PHY_OFDM(0xA2) /* fourwire Control */
#define B43_LPPHY_CPA_TAILCOUNT_VAL B43_PHY_OFDM(0xA3) /* CPA TailCount Value */
#define B43_LPPHY_TX_PWR_CTL_CMD B43_PHY_OFDM(0xA4) /* TX Power Control Cmd */
#define B43_LPPHY_TX_PWR_CTL_CMD_MODE 0xE000 /* TX power control mode mask */
#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF 0x0000 /* TX power control is OFF */
#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW 0x8000 /* TX power control is SOFTWARE */
#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW 0xE000 /* TX power control is HARDWARE */
#define B43_LPPHY_TX_PWR_CTL_NNUM B43_PHY_OFDM(0xA5) /* TX Power Control Nnum */
#define B43_LPPHY_TX_PWR_CTL_IDLETSSI B43_PHY_OFDM(0xA6) /* TX Power Control IdleTssi */
#define B43_LPPHY_TX_PWR_CTL_TARGETPWR B43_PHY_OFDM(0xA7) /* TX Power Control TargetPower */
#define B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT B43_PHY_OFDM(0xA8) /* TX Power Control DeltaPower Limit */
#define B43_LPPHY_TX_PWR_CTL_BASEINDEX B43_PHY_OFDM(0xA9) /* TX Power Control BaseIndex */
#define B43_LPPHY_TX_PWR_CTL_PWR_INDEX B43_PHY_OFDM(0xAA) /* TX Power Control Power Index */
#define B43_LPPHY_TX_PWR_CTL_STAT B43_PHY_OFDM(0xAB) /* TX Power Control Status */
#define B43_LPPHY_LP_RF_SIGNAL_LUT B43_PHY_OFDM(0xAC) /* LP RF signal LUT */
#define B43_LPPHY_RX_RADIO_CTL_FILTER_STATE B43_PHY_OFDM(0xAD) /* RX Radio Control Filter State */
#define B43_LPPHY_RX_RADIO_CTL B43_PHY_OFDM(0xAE) /* RX Radio Control */
#define B43_LPPHY_NRSSI_STAT_ADDR B43_PHY_OFDM(0xAF) /* NRSSI status Address */
#define B43_LPPHY_RF_OVERRIDE_2 B43_PHY_OFDM(0xB0) /* RF override 2 */
#define B43_LPPHY_RF_OVERRIDE_2_VAL B43_PHY_OFDM(0xB1) /* RF override 2 val */
#define B43_LPPHY_PS_CTL_OVERRIDE_VAL0 B43_PHY_OFDM(0xB2) /* PS Control override val0 */
#define B43_LPPHY_PS_CTL_OVERRIDE_VAL1 B43_PHY_OFDM(0xB3) /* PS Control override val1 */
#define B43_LPPHY_PS_CTL_OVERRIDE_VAL2 B43_PHY_OFDM(0xB4) /* PS Control override val2 */
#define B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB5) /* TX gain Control override val */
#define B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB6) /* RX gain Control override val */
#define B43_LPPHY_AFE_DDFS B43_PHY_OFDM(0xB7) /* AFE DDFS */
#define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */
#define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */
#define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */
#define B43_LPPHY_TR_LOOKUP_3 B43_PHY_OFDM(0xBB) /* TR Lookup 3 */
#define B43_LPPHY_TR_LOOKUP_4 B43_PHY_OFDM(0xBC) /* TR Lookup 4 */
#define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */
#define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */
#define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */
#define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */
#define B43_LPPHY_4C3 B43_PHY_OFDM(0xC3) /* unknown, used during BB init */
#define B43_LPPHY_4C4 B43_PHY_OFDM(0xC4) /* unknown, used during BB init */
#define B43_LPPHY_4C5 B43_PHY_OFDM(0xC5) /* unknown, used during BB init */
#define B43_LPPHY_TR_LOOKUP_5 B43_PHY_OFDM(0xC7) /* TR Lookup 5 */
#define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
#define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
#define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
#define B43_LPPHY_RF_PWR_OVERRIDE B43_PHY_OFDM(0xD3) /* RF power override */
/* Radio register access decorators. */
#define B43_LP_RADIO(radio_reg) (radio_reg)
#define B43_LP_NORTH(radio_reg) B43_LP_RADIO(radio_reg)
#define B43_LP_SOUTH(radio_reg) B43_LP_RADIO((radio_reg) | 0x4000)
/*** Broadcom 2062 NORTH radio registers ***/
#define B2062_N_COMM1 B43_LP_NORTH(0x000) /* Common 01 (north) */
#define B2062_N_COMM2 B43_LP_NORTH(0x002) /* Common 02 (north) */
#define B2062_N_COMM3 B43_LP_NORTH(0x003) /* Common 03 (north) */
#define B2062_N_COMM4 B43_LP_NORTH(0x004) /* Common 04 (north) */
#define B2062_N_COMM5 B43_LP_NORTH(0x005) /* Common 05 (north) */
#define B2062_N_COMM6 B43_LP_NORTH(0x006) /* Common 06 (north) */
#define B2062_N_COMM7 B43_LP_NORTH(0x007) /* Common 07 (north) */
#define B2062_N_COMM8 B43_LP_NORTH(0x008) /* Common 08 (north) */
#define B2062_N_COMM9 B43_LP_NORTH(0x009) /* Common 09 (north) */
#define B2062_N_COMM10 B43_LP_NORTH(0x00A) /* Common 10 (north) */
#define B2062_N_COMM11 B43_LP_NORTH(0x00B) /* Common 11 (north) */
#define B2062_N_COMM12 B43_LP_NORTH(0x00C) /* Common 12 (north) */
#define B2062_N_COMM13 B43_LP_NORTH(0x00D) /* Common 13 (north) */
#define B2062_N_COMM14 B43_LP_NORTH(0x00E) /* Common 14 (north) */
#define B2062_N_COMM15 B43_LP_NORTH(0x00F) /* Common 15 (north) */
#define B2062_N_PDN_CTL0 B43_LP_NORTH(0x010) /* PDN Control 0 (north) */
#define B2062_N_PDN_CTL1 B43_LP_NORTH(0x011) /* PDN Control 1 (north) */
#define B2062_N_PDN_CTL2 B43_LP_NORTH(0x012) /* PDN Control 2 (north) */
#define B2062_N_PDN_CTL3 B43_LP_NORTH(0x013) /* PDN Control 3 (north) */
#define B2062_N_PDN_CTL4 B43_LP_NORTH(0x014) /* PDN Control 4 (north) */
#define B2062_N_GEN_CTL0 B43_LP_NORTH(0x015) /* GEN Control 0 (north) */
#define B2062_N_IQ_CALIB B43_LP_NORTH(0x016) /* IQ Calibration (north) */
#define B2062_N_LGENC B43_LP_NORTH(0x017) /* LGENC (north) */
#define B2062_N_LGENA_LPF B43_LP_NORTH(0x018) /* LGENA LPF (north) */
#define B2062_N_LGENA_BIAS0 B43_LP_NORTH(0x019) /* LGENA Bias 0 (north) */
#define B2062_N_LGNEA_BIAS1 B43_LP_NORTH(0x01A) /* LGNEA Bias 1 (north) */
#define B2062_N_LGENA_CTL0 B43_LP_NORTH(0x01B) /* LGENA Control 0 (north) */
#define B2062_N_LGENA_CTL1 B43_LP_NORTH(0x01C) /* LGENA Control 1 (north) */
#define B2062_N_LGENA_CTL2 B43_LP_NORTH(0x01D) /* LGENA Control 2 (north) */
#define B2062_N_LGENA_TUNE0 B43_LP_NORTH(0x01E) /* LGENA Tune 0 (north) */
#define B2062_N_LGENA_TUNE1 B43_LP_NORTH(0x01F) /* LGENA Tune 1 (north) */
#define B2062_N_LGENA_TUNE2 B43_LP_NORTH(0x020) /* LGENA Tune 2 (north) */
#define B2062_N_LGENA_TUNE3 B43_LP_NORTH(0x021) /* LGENA Tune 3 (north) */
#define B2062_N_LGENA_CTL3 B43_LP_NORTH(0x022) /* LGENA Control 3 (north) */
#define B2062_N_LGENA_CTL4 B43_LP_NORTH(0x023) /* LGENA Control 4 (north) */
#define B2062_N_LGENA_CTL5 B43_LP_NORTH(0x024) /* LGENA Control 5 (north) */
#define B2062_N_LGENA_CTL6 B43_LP_NORTH(0x025) /* LGENA Control 6 (north) */
#define B2062_N_LGENA_CTL7 B43_LP_NORTH(0x026) /* LGENA Control 7 (north) */
#define B2062_N_RXA_CTL0 B43_LP_NORTH(0x027) /* RXA Control 0 (north) */
#define B2062_N_RXA_CTL1 B43_LP_NORTH(0x028) /* RXA Control 1 (north) */
#define B2062_N_RXA_CTL2 B43_LP_NORTH(0x029) /* RXA Control 2 (north) */
#define B2062_N_RXA_CTL3 B43_LP_NORTH(0x02A) /* RXA Control 3 (north) */
#define B2062_N_RXA_CTL4 B43_LP_NORTH(0x02B) /* RXA Control 4 (north) */
#define B2062_N_RXA_CTL5 B43_LP_NORTH(0x02C) /* RXA Control 5 (north) */
#define B2062_N_RXA_CTL6 B43_LP_NORTH(0x02D) /* RXA Control 6 (north) */
#define B2062_N_RXA_CTL7 B43_LP_NORTH(0x02E) /* RXA Control 7 (north) */
#define B2062_N_RXBB_CTL0 B43_LP_NORTH(0x02F) /* RXBB Control 0 (north) */
#define B2062_N_RXBB_CTL1 B43_LP_NORTH(0x030) /* RXBB Control 1 (north) */
#define B2062_N_RXBB_CTL2 B43_LP_NORTH(0x031) /* RXBB Control 2 (north) */
#define B2062_N_RXBB_GAIN0 B43_LP_NORTH(0x032) /* RXBB Gain 0 (north) */
#define B2062_N_RXBB_GAIN1 B43_LP_NORTH(0x033) /* RXBB Gain 1 (north) */
#define B2062_N_RXBB_GAIN2 B43_LP_NORTH(0x034) /* RXBB Gain 2 (north) */
#define B2062_N_RXBB_GAIN3 B43_LP_NORTH(0x035) /* RXBB Gain 3 (north) */
#define B2062_N_RXBB_RSSI0 B43_LP_NORTH(0x036) /* RXBB RSSI 0 (north) */
#define B2062_N_RXBB_RSSI1 B43_LP_NORTH(0x037) /* RXBB RSSI 1 (north) */
#define B2062_N_RXBB_CALIB0 B43_LP_NORTH(0x038) /* RXBB Calibration0 (north) */
#define B2062_N_RXBB_CALIB1 B43_LP_NORTH(0x039) /* RXBB Calibration1 (north) */
#define B2062_N_RXBB_CALIB2 B43_LP_NORTH(0x03A) /* RXBB Calibration2 (north) */
#define B2062_N_RXBB_BIAS0 B43_LP_NORTH(0x03B) /* RXBB Bias 0 (north) */
#define B2062_N_RXBB_BIAS1 B43_LP_NORTH(0x03C) /* RXBB Bias 1 (north) */
#define B2062_N_RXBB_BIAS2 B43_LP_NORTH(0x03D) /* RXBB Bias 2 (north) */
#define B2062_N_RXBB_BIAS3 B43_LP_NORTH(0x03E) /* RXBB Bias 3 (north) */
#define B2062_N_RXBB_BIAS4 B43_LP_NORTH(0x03F) /* RXBB Bias 4 (north) */
#define B2062_N_RXBB_BIAS5 B43_LP_NORTH(0x040) /* RXBB Bias 5 (north) */
#define B2062_N_RXBB_RSSI2 B43_LP_NORTH(0x041) /* RXBB RSSI 2 (north) */
#define B2062_N_RXBB_RSSI3 B43_LP_NORTH(0x042) /* RXBB RSSI 3 (north) */
#define B2062_N_RXBB_RSSI4 B43_LP_NORTH(0x043) /* RXBB RSSI 4 (north) */
#define B2062_N_RXBB_RSSI5 B43_LP_NORTH(0x044) /* RXBB RSSI 5 (north) */
#define B2062_N_TX_CTL0 B43_LP_NORTH(0x045) /* TX Control 0 (north) */
#define B2062_N_TX_CTL1 B43_LP_NORTH(0x046) /* TX Control 1 (north) */
#define B2062_N_TX_CTL2 B43_LP_NORTH(0x047) /* TX Control 2 (north) */
#define B2062_N_TX_CTL3 B43_LP_NORTH(0x048) /* TX Control 3 (north) */
#define B2062_N_TX_CTL4 B43_LP_NORTH(0x049) /* TX Control 4 (north) */
#define B2062_N_TX_CTL5 B43_LP_NORTH(0x04A) /* TX Control 5 (north) */
#define B2062_N_TX_CTL6 B43_LP_NORTH(0x04B) /* TX Control 6 (north) */
#define B2062_N_TX_CTL7 B43_LP_NORTH(0x04C) /* TX Control 7 (north) */
#define B2062_N_TX_CTL8 B43_LP_NORTH(0x04D) /* TX Control 8 (north) */
#define B2062_N_TX_CTL9 B43_LP_NORTH(0x04E) /* TX Control 9 (north) */
#define B2062_N_TX_CTL_A B43_LP_NORTH(0x04F) /* TX Control A (north) */
#define B2062_N_TX_GC2G B43_LP_NORTH(0x050) /* TX GC2G (north) */
#define B2062_N_TX_GC5G B43_LP_NORTH(0x051) /* TX GC5G (north) */
#define B2062_N_TX_TUNE B43_LP_NORTH(0x052) /* TX Tune (north) */
#define B2062_N_TX_PAD B43_LP_NORTH(0x053) /* TX PAD (north) */
#define B2062_N_TX_PGA B43_LP_NORTH(0x054) /* TX PGA (north) */
#define B2062_N_TX_PADAUX B43_LP_NORTH(0x055) /* TX PADAUX (north) */
#define B2062_N_TX_PGAAUX B43_LP_NORTH(0x056) /* TX PGAAUX (north) */
#define B2062_N_TSSI_CTL0 B43_LP_NORTH(0x057) /* TSSI Control 0 (north) */
#define B2062_N_TSSI_CTL1 B43_LP_NORTH(0x058) /* TSSI Control 1 (north) */
#define B2062_N_TSSI_CTL2 B43_LP_NORTH(0x059) /* TSSI Control 2 (north) */
#define B2062_N_IQ_CALIB_CTL0 B43_LP_NORTH(0x05A) /* IQ Calibration Control 0 (north) */
#define B2062_N_IQ_CALIB_CTL1 B43_LP_NORTH(0x05B) /* IQ Calibration Control 1 (north) */
#define B2062_N_IQ_CALIB_CTL2 B43_LP_NORTH(0x05C) /* IQ Calibration Control 2 (north) */
#define B2062_N_CALIB_TS B43_LP_NORTH(0x05D) /* Calibration TS (north) */
#define B2062_N_CALIB_CTL0 B43_LP_NORTH(0x05E) /* Calibration Control 0 (north) */
#define B2062_N_CALIB_CTL1 B43_LP_NORTH(0x05F) /* Calibration Control 1 (north) */
#define B2062_N_CALIB_CTL2 B43_LP_NORTH(0x060) /* Calibration Control 2 (north) */
#define B2062_N_CALIB_CTL3 B43_LP_NORTH(0x061) /* Calibration Control 3 (north) */
#define B2062_N_CALIB_CTL4 B43_LP_NORTH(0x062) /* Calibration Control 4 (north) */
#define B2062_N_CALIB_DBG0 B43_LP_NORTH(0x063) /* Calibration Debug 0 (north) */
#define B2062_N_CALIB_DBG1 B43_LP_NORTH(0x064) /* Calibration Debug 1 (north) */
#define B2062_N_CALIB_DBG2 B43_LP_NORTH(0x065) /* Calibration Debug 2 (north) */
#define B2062_N_CALIB_DBG3 B43_LP_NORTH(0x066) /* Calibration Debug 3 (north) */
#define B2062_N_PSENSE_CTL0 B43_LP_NORTH(0x069) /* PSENSE Control 0 (north) */
#define B2062_N_PSENSE_CTL1 B43_LP_NORTH(0x06A) /* PSENSE Control 1 (north) */
#define B2062_N_PSENSE_CTL2 B43_LP_NORTH(0x06B) /* PSENSE Control 2 (north) */
#define B2062_N_TEST_BUF0 B43_LP_NORTH(0x06C) /* TEST BUF0 (north) */
/*** Broadcom 2062 SOUTH radio registers ***/
#define B2062_S_COMM1 B43_LP_SOUTH(0x000) /* Common 01 (south) */
#define B2062_S_RADIO_ID_CODE B43_LP_SOUTH(0x001) /* Radio ID code (south) */
#define B2062_S_COMM2 B43_LP_SOUTH(0x002) /* Common 02 (south) */
#define B2062_S_COMM3 B43_LP_SOUTH(0x003) /* Common 03 (south) */
#define B2062_S_COMM4 B43_LP_SOUTH(0x004) /* Common 04 (south) */
#define B2062_S_COMM5 B43_LP_SOUTH(0x005) /* Common 05 (south) */
#define B2062_S_COMM6 B43_LP_SOUTH(0x006) /* Common 06 (south) */
#define B2062_S_COMM7 B43_LP_SOUTH(0x007) /* Common 07 (south) */
#define B2062_S_COMM8 B43_LP_SOUTH(0x008) /* Common 08 (south) */
#define B2062_S_COMM9 B43_LP_SOUTH(0x009) /* Common 09 (south) */
#define B2062_S_COMM10 B43_LP_SOUTH(0x00A) /* Common 10 (south) */
#define B2062_S_COMM11 B43_LP_SOUTH(0x00B) /* Common 11 (south) */
#define B2062_S_COMM12 B43_LP_SOUTH(0x00C) /* Common 12 (south) */
#define B2062_S_COMM13 B43_LP_SOUTH(0x00D) /* Common 13 (south) */
#define B2062_S_COMM14 B43_LP_SOUTH(0x00E) /* Common 14 (south) */
#define B2062_S_COMM15 B43_LP_SOUTH(0x00F) /* Common 15 (south) */
#define B2062_S_PDS_CTL0 B43_LP_SOUTH(0x010) /* PDS Control 0 (south) */
#define B2062_S_PDS_CTL1 B43_LP_SOUTH(0x011) /* PDS Control 1 (south) */
#define B2062_S_PDS_CTL2 B43_LP_SOUTH(0x012) /* PDS Control 2 (south) */
#define B2062_S_PDS_CTL3 B43_LP_SOUTH(0x013) /* PDS Control 3 (south) */
#define B2062_S_BG_CTL0 B43_LP_SOUTH(0x014) /* BG Control 0 (south) */
#define B2062_S_BG_CTL1 B43_LP_SOUTH(0x015) /* BG Control 1 (south) */
#define B2062_S_BG_CTL2 B43_LP_SOUTH(0x016) /* BG Control 2 (south) */
#define B2062_S_LGENG_CTL0 B43_LP_SOUTH(0x017) /* LGENG Control 00 (south) */
#define B2062_S_LGENG_CTL1 B43_LP_SOUTH(0x018) /* LGENG Control 01 (south) */
#define B2062_S_LGENG_CTL2 B43_LP_SOUTH(0x019) /* LGENG Control 02 (south) */
#define B2062_S_LGENG_CTL3 B43_LP_SOUTH(0x01A) /* LGENG Control 03 (south) */
#define B2062_S_LGENG_CTL4 B43_LP_SOUTH(0x01B) /* LGENG Control 04 (south) */
#define B2062_S_LGENG_CTL5 B43_LP_SOUTH(0x01C) /* LGENG Control 05 (south) */
#define B2062_S_LGENG_CTL6 B43_LP_SOUTH(0x01D) /* LGENG Control 06 (south) */
#define B2062_S_LGENG_CTL7 B43_LP_SOUTH(0x01E) /* LGENG Control 07 (south) */
#define B2062_S_LGENG_CTL8 B43_LP_SOUTH(0x01F) /* LGENG Control 08 (south) */
#define B2062_S_LGENG_CTL9 B43_LP_SOUTH(0x020) /* LGENG Control 09 (south) */
#define B2062_S_LGENG_CTL10 B43_LP_SOUTH(0x021) /* LGENG Control 10 (south) */
#define B2062_S_LGENG_CTL11 B43_LP_SOUTH(0x022) /* LGENG Control 11 (south) */
#define B2062_S_REFPLL_CTL0 B43_LP_SOUTH(0x023) /* REFPLL Control 00 (south) */
#define B2062_S_REFPLL_CTL1 B43_LP_SOUTH(0x024) /* REFPLL Control 01 (south) */
#define B2062_S_REFPLL_CTL2 B43_LP_SOUTH(0x025) /* REFPLL Control 02 (south) */
#define B2062_S_REFPLL_CTL3 B43_LP_SOUTH(0x026) /* REFPLL Control 03 (south) */
#define B2062_S_REFPLL_CTL4 B43_LP_SOUTH(0x027) /* REFPLL Control 04 (south) */
#define B2062_S_REFPLL_CTL5 B43_LP_SOUTH(0x028) /* REFPLL Control 05 (south) */
#define B2062_S_REFPLL_CTL6 B43_LP_SOUTH(0x029) /* REFPLL Control 06 (south) */
#define B2062_S_REFPLL_CTL7 B43_LP_SOUTH(0x02A) /* REFPLL Control 07 (south) */
#define B2062_S_REFPLL_CTL8 B43_LP_SOUTH(0x02B) /* REFPLL Control 08 (south) */
#define B2062_S_REFPLL_CTL9 B43_LP_SOUTH(0x02C) /* REFPLL Control 09 (south) */
#define B2062_S_REFPLL_CTL10 B43_LP_SOUTH(0x02D) /* REFPLL Control 10 (south) */
#define B2062_S_REFPLL_CTL11 B43_LP_SOUTH(0x02E) /* REFPLL Control 11 (south) */
#define B2062_S_REFPLL_CTL12 B43_LP_SOUTH(0x02F) /* REFPLL Control 12 (south) */
#define B2062_S_REFPLL_CTL13 B43_LP_SOUTH(0x030) /* REFPLL Control 13 (south) */
#define B2062_S_REFPLL_CTL14 B43_LP_SOUTH(0x031) /* REFPLL Control 14 (south) */
#define B2062_S_REFPLL_CTL15 B43_LP_SOUTH(0x032) /* REFPLL Control 15 (south) */
#define B2062_S_REFPLL_CTL16 B43_LP_SOUTH(0x033) /* REFPLL Control 16 (south) */
#define B2062_S_RFPLL_CTL0 B43_LP_SOUTH(0x034) /* RFPLL Control 00 (south) */
#define B2062_S_RFPLL_CTL1 B43_LP_SOUTH(0x035) /* RFPLL Control 01 (south) */
#define B2062_S_RFPLL_CTL2 B43_LP_SOUTH(0x036) /* RFPLL Control 02 (south) */
#define B2062_S_RFPLL_CTL3 B43_LP_SOUTH(0x037) /* RFPLL Control 03 (south) */
#define B2062_S_RFPLL_CTL4 B43_LP_SOUTH(0x038) /* RFPLL Control 04 (south) */
#define B2062_S_RFPLL_CTL5 B43_LP_SOUTH(0x039) /* RFPLL Control 05 (south) */
#define B2062_S_RFPLL_CTL6 B43_LP_SOUTH(0x03A) /* RFPLL Control 06 (south) */
#define B2062_S_RFPLL_CTL7 B43_LP_SOUTH(0x03B) /* RFPLL Control 07 (south) */
#define B2062_S_RFPLL_CTL8 B43_LP_SOUTH(0x03C) /* RFPLL Control 08 (south) */
#define B2062_S_RFPLL_CTL9 B43_LP_SOUTH(0x03D) /* RFPLL Control 09 (south) */
#define B2062_S_RFPLL_CTL10 B43_LP_SOUTH(0x03E) /* RFPLL Control 10 (south) */
#define B2062_S_RFPLL_CTL11 B43_LP_SOUTH(0x03F) /* RFPLL Control 11 (south) */
#define B2062_S_RFPLL_CTL12 B43_LP_SOUTH(0x040) /* RFPLL Control 12 (south) */
#define B2062_S_RFPLL_CTL13 B43_LP_SOUTH(0x041) /* RFPLL Control 13 (south) */
#define B2062_S_RFPLL_CTL14 B43_LP_SOUTH(0x042) /* RFPLL Control 14 (south) */
#define B2062_S_RFPLL_CTL15 B43_LP_SOUTH(0x043) /* RFPLL Control 15 (south) */
#define B2062_S_RFPLL_CTL16 B43_LP_SOUTH(0x044) /* RFPLL Control 16 (south) */
#define B2062_S_RFPLL_CTL17 B43_LP_SOUTH(0x045) /* RFPLL Control 17 (south) */
#define B2062_S_RFPLL_CTL18 B43_LP_SOUTH(0x046) /* RFPLL Control 18 (south) */
#define B2062_S_RFPLL_CTL19 B43_LP_SOUTH(0x047) /* RFPLL Control 19 (south) */
#define B2062_S_RFPLL_CTL20 B43_LP_SOUTH(0x048) /* RFPLL Control 20 (south) */
#define B2062_S_RFPLL_CTL21 B43_LP_SOUTH(0x049) /* RFPLL Control 21 (south) */
#define B2062_S_RFPLL_CTL22 B43_LP_SOUTH(0x04A) /* RFPLL Control 22 (south) */
#define B2062_S_RFPLL_CTL23 B43_LP_SOUTH(0x04B) /* RFPLL Control 23 (south) */
#define B2062_S_RFPLL_CTL24 B43_LP_SOUTH(0x04C) /* RFPLL Control 24 (south) */
#define B2062_S_RFPLL_CTL25 B43_LP_SOUTH(0x04D) /* RFPLL Control 25 (south) */
#define B2062_S_RFPLL_CTL26 B43_LP_SOUTH(0x04E) /* RFPLL Control 26 (south) */
#define B2062_S_RFPLL_CTL27 B43_LP_SOUTH(0x04F) /* RFPLL Control 27 (south) */
#define B2062_S_RFPLL_CTL28 B43_LP_SOUTH(0x050) /* RFPLL Control 28 (south) */
#define B2062_S_RFPLL_CTL29 B43_LP_SOUTH(0x051) /* RFPLL Control 29 (south) */
#define B2062_S_RFPLL_CTL30 B43_LP_SOUTH(0x052) /* RFPLL Control 30 (south) */
#define B2062_S_RFPLL_CTL31 B43_LP_SOUTH(0x053) /* RFPLL Control 31 (south) */
#define B2062_S_RFPLL_CTL32 B43_LP_SOUTH(0x054) /* RFPLL Control 32 (south) */
#define B2062_S_RFPLL_CTL33 B43_LP_SOUTH(0x055) /* RFPLL Control 33 (south) */
#define B2062_S_RFPLL_CTL34 B43_LP_SOUTH(0x056) /* RFPLL Control 34 (south) */
#define B2062_S_RXG_CNT0 B43_LP_SOUTH(0x057) /* RXG Counter 00 (south) */
#define B2062_S_RXG_CNT1 B43_LP_SOUTH(0x058) /* RXG Counter 01 (south) */
#define B2062_S_RXG_CNT2 B43_LP_SOUTH(0x059) /* RXG Counter 02 (south) */
#define B2062_S_RXG_CNT3 B43_LP_SOUTH(0x05A) /* RXG Counter 03 (south) */
#define B2062_S_RXG_CNT4 B43_LP_SOUTH(0x05B) /* RXG Counter 04 (south) */
#define B2062_S_RXG_CNT5 B43_LP_SOUTH(0x05C) /* RXG Counter 05 (south) */
#define B2062_S_RXG_CNT6 B43_LP_SOUTH(0x05D) /* RXG Counter 06 (south) */
#define B2062_S_RXG_CNT7 B43_LP_SOUTH(0x05E) /* RXG Counter 07 (south) */
#define B2062_S_RXG_CNT8 B43_LP_SOUTH(0x05F) /* RXG Counter 08 (south) */
#define B2062_S_RXG_CNT9 B43_LP_SOUTH(0x060) /* RXG Counter 09 (south) */
#define B2062_S_RXG_CNT10 B43_LP_SOUTH(0x061) /* RXG Counter 10 (south) */
#define B2062_S_RXG_CNT11 B43_LP_SOUTH(0x062) /* RXG Counter 11 (south) */
#define B2062_S_RXG_CNT12 B43_LP_SOUTH(0x063) /* RXG Counter 12 (south) */
#define B2062_S_RXG_CNT13 B43_LP_SOUTH(0x064) /* RXG Counter 13 (south) */
#define B2062_S_RXG_CNT14 B43_LP_SOUTH(0x065) /* RXG Counter 14 (south) */
#define B2062_S_RXG_CNT15 B43_LP_SOUTH(0x066) /* RXG Counter 15 (south) */
#define B2062_S_RXG_CNT16 B43_LP_SOUTH(0x067) /* RXG Counter 16 (south) */
#define B2062_S_RXG_CNT17 B43_LP_SOUTH(0x068) /* RXG Counter 17 (south) */
/*** Broadcom 2063 radio registers ***/
#define B2063_RADIO_ID_CODE B43_LP_RADIO(0x001) /* Radio ID code */
#define B2063_COMM1 B43_LP_RADIO(0x000) /* Common 01 */
#define B2063_COMM2 B43_LP_RADIO(0x002) /* Common 02 */
#define B2063_COMM3 B43_LP_RADIO(0x003) /* Common 03 */
#define B2063_COMM4 B43_LP_RADIO(0x004) /* Common 04 */
#define B2063_COMM5 B43_LP_RADIO(0x005) /* Common 05 */
#define B2063_COMM6 B43_LP_RADIO(0x006) /* Common 06 */
#define B2063_COMM7 B43_LP_RADIO(0x007) /* Common 07 */
#define B2063_COMM8 B43_LP_RADIO(0x008) /* Common 08 */
#define B2063_COMM9 B43_LP_RADIO(0x009) /* Common 09 */
#define B2063_COMM10 B43_LP_RADIO(0x00A) /* Common 10 */
#define B2063_COMM11 B43_LP_RADIO(0x00B) /* Common 11 */
#define B2063_COMM12 B43_LP_RADIO(0x00C) /* Common 12 */
#define B2063_COMM13 B43_LP_RADIO(0x00D) /* Common 13 */
#define B2063_COMM14 B43_LP_RADIO(0x00E) /* Common 14 */
#define B2063_COMM15 B43_LP_RADIO(0x00F) /* Common 15 */
#define B2063_COMM16 B43_LP_RADIO(0x010) /* Common 16 */
#define B2063_COMM17 B43_LP_RADIO(0x011) /* Common 17 */
#define B2063_COMM18 B43_LP_RADIO(0x012) /* Common 18 */
#define B2063_COMM19 B43_LP_RADIO(0x013) /* Common 19 */
#define B2063_COMM20 B43_LP_RADIO(0x014) /* Common 20 */
#define B2063_COMM21 B43_LP_RADIO(0x015) /* Common 21 */
#define B2063_COMM22 B43_LP_RADIO(0x016) /* Common 22 */
#define B2063_COMM23 B43_LP_RADIO(0x017) /* Common 23 */
#define B2063_COMM24 B43_LP_RADIO(0x018) /* Common 24 */
#define B2063_PWR_SWITCH_CTL B43_LP_RADIO(0x019) /* POWER SWITCH Control */
#define B2063_PLL_SP1 B43_LP_RADIO(0x01A) /* PLL SP 1 */
#define B2063_PLL_SP2 B43_LP_RADIO(0x01B) /* PLL SP 2 */
#define B2063_LOGEN_SP1 B43_LP_RADIO(0x01C) /* LOGEN SP 1 */
#define B2063_LOGEN_SP2 B43_LP_RADIO(0x01D) /* LOGEN SP 2 */
#define B2063_LOGEN_SP3 B43_LP_RADIO(0x01E) /* LOGEN SP 3 */
#define B2063_LOGEN_SP4 B43_LP_RADIO(0x01F) /* LOGEN SP 4 */
#define B2063_LOGEN_SP5 B43_LP_RADIO(0x020) /* LOGEN SP 5 */
#define B2063_G_RX_SP1 B43_LP_RADIO(0x021) /* G RX SP 1 */
#define B2063_G_RX_SP2 B43_LP_RADIO(0x022) /* G RX SP 2 */
#define B2063_G_RX_SP3 B43_LP_RADIO(0x023) /* G RX SP 3 */
#define B2063_G_RX_SP4 B43_LP_RADIO(0x024) /* G RX SP 4 */
#define B2063_G_RX_SP5 B43_LP_RADIO(0x025) /* G RX SP 5 */
#define B2063_G_RX_SP6 B43_LP_RADIO(0x026) /* G RX SP 6 */
#define B2063_G_RX_SP7 B43_LP_RADIO(0x027) /* G RX SP 7 */
#define B2063_G_RX_SP8 B43_LP_RADIO(0x028) /* G RX SP 8 */
#define B2063_G_RX_SP9 B43_LP_RADIO(0x029) /* G RX SP 9 */
#define B2063_G_RX_SP10 B43_LP_RADIO(0x02A) /* G RX SP 10 */
#define B2063_G_RX_SP11 B43_LP_RADIO(0x02B) /* G RX SP 11 */
#define B2063_A_RX_SP1 B43_LP_RADIO(0x02C) /* A RX SP 1 */
#define B2063_A_RX_SP2 B43_LP_RADIO(0x02D) /* A RX SP 2 */
#define B2063_A_RX_SP3 B43_LP_RADIO(0x02E) /* A RX SP 3 */
#define B2063_A_RX_SP4 B43_LP_RADIO(0x02F) /* A RX SP 4 */
#define B2063_A_RX_SP5 B43_LP_RADIO(0x030) /* A RX SP 5 */
#define B2063_A_RX_SP6 B43_LP_RADIO(0x031) /* A RX SP 6 */
#define B2063_A_RX_SP7 B43_LP_RADIO(0x032) /* A RX SP 7 */
#define B2063_RX_BB_SP1 B43_LP_RADIO(0x033) /* RX BB SP 1 */
#define B2063_RX_BB_SP2 B43_LP_RADIO(0x034) /* RX BB SP 2 */
#define B2063_RX_BB_SP3 B43_LP_RADIO(0x035) /* RX BB SP 3 */
#define B2063_RX_BB_SP4 B43_LP_RADIO(0x036) /* RX BB SP 4 */
#define B2063_RX_BB_SP5 B43_LP_RADIO(0x037) /* RX BB SP 5 */
#define B2063_RX_BB_SP6 B43_LP_RADIO(0x038) /* RX BB SP 6 */
#define B2063_RX_BB_SP7 B43_LP_RADIO(0x039) /* RX BB SP 7 */
#define B2063_RX_BB_SP8 B43_LP_RADIO(0x03A) /* RX BB SP 8 */
#define B2063_TX_RF_SP1 B43_LP_RADIO(0x03B) /* TX RF SP 1 */
#define B2063_TX_RF_SP2 B43_LP_RADIO(0x03C) /* TX RF SP 2 */
#define B2063_TX_RF_SP3 B43_LP_RADIO(0x03D) /* TX RF SP 3 */
#define B2063_TX_RF_SP4 B43_LP_RADIO(0x03E) /* TX RF SP 4 */
#define B2063_TX_RF_SP5 B43_LP_RADIO(0x03F) /* TX RF SP 5 */
#define B2063_TX_RF_SP6 B43_LP_RADIO(0x040) /* TX RF SP 6 */
#define B2063_TX_RF_SP7 B43_LP_RADIO(0x041) /* TX RF SP 7 */
#define B2063_TX_RF_SP8 B43_LP_RADIO(0x042) /* TX RF SP 8 */
#define B2063_TX_RF_SP9 B43_LP_RADIO(0x043) /* TX RF SP 9 */
#define B2063_TX_RF_SP10 B43_LP_RADIO(0x044) /* TX RF SP 10 */
#define B2063_TX_RF_SP11 B43_LP_RADIO(0x045) /* TX RF SP 11 */
#define B2063_TX_RF_SP12 B43_LP_RADIO(0x046) /* TX RF SP 12 */
#define B2063_TX_RF_SP13 B43_LP_RADIO(0x047) /* TX RF SP 13 */
#define B2063_TX_RF_SP14 B43_LP_RADIO(0x048) /* TX RF SP 14 */
#define B2063_TX_RF_SP15 B43_LP_RADIO(0x049) /* TX RF SP 15 */
#define B2063_TX_RF_SP16 B43_LP_RADIO(0x04A) /* TX RF SP 16 */
#define B2063_TX_RF_SP17 B43_LP_RADIO(0x04B) /* TX RF SP 17 */
#define B2063_PA_SP1 B43_LP_RADIO(0x04C) /* PA SP 1 */
#define B2063_PA_SP2 B43_LP_RADIO(0x04D) /* PA SP 2 */
#define B2063_PA_SP3 B43_LP_RADIO(0x04E) /* PA SP 3 */
#define B2063_PA_SP4 B43_LP_RADIO(0x04F) /* PA SP 4 */
#define B2063_PA_SP5 B43_LP_RADIO(0x050) /* PA SP 5 */
#define B2063_PA_SP6 B43_LP_RADIO(0x051) /* PA SP 6 */
#define B2063_PA_SP7 B43_LP_RADIO(0x052) /* PA SP 7 */
#define B2063_TX_BB_SP1 B43_LP_RADIO(0x053) /* TX BB SP 1 */
#define B2063_TX_BB_SP2 B43_LP_RADIO(0x054) /* TX BB SP 2 */
#define B2063_TX_BB_SP3 B43_LP_RADIO(0x055) /* TX BB SP 3 */
#define B2063_REG_SP1 B43_LP_RADIO(0x056) /* REG SP 1 */
#define B2063_BANDGAP_CTL1 B43_LP_RADIO(0x057) /* BANDGAP Control 1 */
#define B2063_BANDGAP_CTL2 B43_LP_RADIO(0x058) /* BANDGAP Control 2 */
#define B2063_LPO_CTL1 B43_LP_RADIO(0x059) /* LPO Control 1 */
#define B2063_RC_CALIB_CTL1 B43_LP_RADIO(0x05A) /* RC Calibration Control 1 */
#define B2063_RC_CALIB_CTL2 B43_LP_RADIO(0x05B) /* RC Calibration Control 2 */
#define B2063_RC_CALIB_CTL3 B43_LP_RADIO(0x05C) /* RC Calibration Control 3 */
#define B2063_RC_CALIB_CTL4 B43_LP_RADIO(0x05D) /* RC Calibration Control 4 */
#define B2063_RC_CALIB_CTL5 B43_LP_RADIO(0x05E) /* RC Calibration Control 5 */
#define B2063_RC_CALIB_CTL6 B43_LP_RADIO(0x05F) /* RC Calibration Control 6 */
#define B2063_RC_CALIB_CTL7 B43_LP_RADIO(0x060) /* RC Calibration Control 7 */
#define B2063_RC_CALIB_CTL8 B43_LP_RADIO(0x061) /* RC Calibration Control 8 */
#define B2063_RC_CALIB_CTL9 B43_LP_RADIO(0x062) /* RC Calibration Control 9 */
#define B2063_RC_CALIB_CTL10 B43_LP_RADIO(0x063) /* RC Calibration Control 10 */
#define B2063_PLL_JTAG_CALNRST B43_LP_RADIO(0x064) /* PLL JTAG CALNRST */
#define B2063_PLL_JTAG_IN_PLL1 B43_LP_RADIO(0x065) /* PLL JTAG IN PLL 1 */
#define B2063_PLL_JTAG_IN_PLL2 B43_LP_RADIO(0x066) /* PLL JTAG IN PLL 2 */
#define B2063_PLL_JTAG_PLL_CP1 B43_LP_RADIO(0x067) /* PLL JTAG PLL CP 1 */
#define B2063_PLL_JTAG_PLL_CP2 B43_LP_RADIO(0x068) /* PLL JTAG PLL CP 2 */
#define B2063_PLL_JTAG_PLL_CP3 B43_LP_RADIO(0x069) /* PLL JTAG PLL CP 3 */
#define B2063_PLL_JTAG_PLL_CP4 B43_LP_RADIO(0x06A) /* PLL JTAG PLL CP 4 */
#define B2063_PLL_JTAG_PLL_CTL1 B43_LP_RADIO(0x06B) /* PLL JTAG PLL Control 1 */
#define B2063_PLL_JTAG_PLL_LF1 B43_LP_RADIO(0x06C) /* PLL JTAG PLL LF 1 */
#define B2063_PLL_JTAG_PLL_LF2 B43_LP_RADIO(0x06D) /* PLL JTAG PLL LF 2 */
#define B2063_PLL_JTAG_PLL_LF3 B43_LP_RADIO(0x06E) /* PLL JTAG PLL LF 3 */
#define B2063_PLL_JTAG_PLL_LF4 B43_LP_RADIO(0x06F) /* PLL JTAG PLL LF 4 */
#define B2063_PLL_JTAG_PLL_SG1 B43_LP_RADIO(0x070) /* PLL JTAG PLL SG 1 */
#define B2063_PLL_JTAG_PLL_SG2 B43_LP_RADIO(0x071) /* PLL JTAG PLL SG 2 */
#define B2063_PLL_JTAG_PLL_SG3 B43_LP_RADIO(0x072) /* PLL JTAG PLL SG 3 */
#define B2063_PLL_JTAG_PLL_SG4 B43_LP_RADIO(0x073) /* PLL JTAG PLL SG 4 */
#define B2063_PLL_JTAG_PLL_SG5 B43_LP_RADIO(0x074) /* PLL JTAG PLL SG 5 */
#define B2063_PLL_JTAG_PLL_VCO1 B43_LP_RADIO(0x075) /* PLL JTAG PLL VCO 1 */
#define B2063_PLL_JTAG_PLL_VCO2 B43_LP_RADIO(0x076) /* PLL JTAG PLL VCO 2 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB1 B43_LP_RADIO(0x077) /* PLL JTAG PLL VCO Calibration 1 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB2 B43_LP_RADIO(0x078) /* PLL JTAG PLL VCO Calibration 2 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB3 B43_LP_RADIO(0x079) /* PLL JTAG PLL VCO Calibration 3 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB4 B43_LP_RADIO(0x07A) /* PLL JTAG PLL VCO Calibration 4 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB5 B43_LP_RADIO(0x07B) /* PLL JTAG PLL VCO Calibration 5 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB6 B43_LP_RADIO(0x07C) /* PLL JTAG PLL VCO Calibration 6 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB7 B43_LP_RADIO(0x07D) /* PLL JTAG PLL VCO Calibration 7 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB8 B43_LP_RADIO(0x07E) /* PLL JTAG PLL VCO Calibration 8 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB9 B43_LP_RADIO(0x07F) /* PLL JTAG PLL VCO Calibration 9 */
#define B2063_PLL_JTAG_PLL_VCO_CALIB10 B43_LP_RADIO(0x080) /* PLL JTAG PLL VCO Calibration 10 */
#define B2063_PLL_JTAG_PLL_XTAL_12 B43_LP_RADIO(0x081) /* PLL JTAG PLL XTAL 1 2 */
#define B2063_PLL_JTAG_PLL_XTAL3 B43_LP_RADIO(0x082) /* PLL JTAG PLL XTAL 3 */
#define B2063_LOGEN_ACL1 B43_LP_RADIO(0x083) /* LOGEN ACL 1 */
#define B2063_LOGEN_ACL2 B43_LP_RADIO(0x084) /* LOGEN ACL 2 */
#define B2063_LOGEN_ACL3 B43_LP_RADIO(0x085) /* LOGEN ACL 3 */
#define B2063_LOGEN_ACL4 B43_LP_RADIO(0x086) /* LOGEN ACL 4 */
#define B2063_LOGEN_ACL5 B43_LP_RADIO(0x087) /* LOGEN ACL 5 */
#define B2063_LO_CALIB_INPUTS B43_LP_RADIO(0x088) /* LO Calibration INPUTS */
#define B2063_LO_CALIB_CTL1 B43_LP_RADIO(0x089) /* LO Calibration Control 1 */
#define B2063_LO_CALIB_CTL2 B43_LP_RADIO(0x08A) /* LO Calibration Control 2 */
#define B2063_LO_CALIB_CTL3 B43_LP_RADIO(0x08B) /* LO Calibration Control 3 */
#define B2063_LO_CALIB_WAITCNT B43_LP_RADIO(0x08C) /* LO Calibration WAITCNT */
#define B2063_LO_CALIB_OVR1 B43_LP_RADIO(0x08D) /* LO Calibration OVR 1 */
#define B2063_LO_CALIB_OVR2 B43_LP_RADIO(0x08E) /* LO Calibration OVR 2 */
#define B2063_LO_CALIB_OVAL1 B43_LP_RADIO(0x08F) /* LO Calibration OVAL 1 */
#define B2063_LO_CALIB_OVAL2 B43_LP_RADIO(0x090) /* LO Calibration OVAL 2 */
#define B2063_LO_CALIB_OVAL3 B43_LP_RADIO(0x091) /* LO Calibration OVAL 3 */
#define B2063_LO_CALIB_OVAL4 B43_LP_RADIO(0x092) /* LO Calibration OVAL 4 */
#define B2063_LO_CALIB_OVAL5 B43_LP_RADIO(0x093) /* LO Calibration OVAL 5 */
#define B2063_LO_CALIB_OVAL6 B43_LP_RADIO(0x094) /* LO Calibration OVAL 6 */
#define B2063_LO_CALIB_OVAL7 B43_LP_RADIO(0x095) /* LO Calibration OVAL 7 */
#define B2063_LO_CALIB_CALVLD1 B43_LP_RADIO(0x096) /* LO Calibration CALVLD 1 */
#define B2063_LO_CALIB_CALVLD2 B43_LP_RADIO(0x097) /* LO Calibration CALVLD 2 */
#define B2063_LO_CALIB_CVAL1 B43_LP_RADIO(0x098) /* LO Calibration CVAL 1 */
#define B2063_LO_CALIB_CVAL2 B43_LP_RADIO(0x099) /* LO Calibration CVAL 2 */
#define B2063_LO_CALIB_CVAL3 B43_LP_RADIO(0x09A) /* LO Calibration CVAL 3 */
#define B2063_LO_CALIB_CVAL4 B43_LP_RADIO(0x09B) /* LO Calibration CVAL 4 */
#define B2063_LO_CALIB_CVAL5 B43_LP_RADIO(0x09C) /* LO Calibration CVAL 5 */
#define B2063_LO_CALIB_CVAL6 B43_LP_RADIO(0x09D) /* LO Calibration CVAL 6 */
#define B2063_LO_CALIB_CVAL7 B43_LP_RADIO(0x09E) /* LO Calibration CVAL 7 */
#define B2063_LOGEN_CALIB_EN B43_LP_RADIO(0x09F) /* LOGEN Calibration EN */
#define B2063_LOGEN_PEAKDET1 B43_LP_RADIO(0x0A0) /* LOGEN PEAKDET 1 */
#define B2063_LOGEN_RCCR1 B43_LP_RADIO(0x0A1) /* LOGEN RCCR 1 */
#define B2063_LOGEN_VCOBUF1 B43_LP_RADIO(0x0A2) /* LOGEN VCOBUF 1 */
#define B2063_LOGEN_MIXER1 B43_LP_RADIO(0x0A3) /* LOGEN MIXER 1 */
#define B2063_LOGEN_MIXER2 B43_LP_RADIO(0x0A4) /* LOGEN MIXER 2 */
#define B2063_LOGEN_BUF1 B43_LP_RADIO(0x0A5) /* LOGEN BUF 1 */
#define B2063_LOGEN_BUF2 B43_LP_RADIO(0x0A6) /* LOGEN BUF 2 */
#define B2063_LOGEN_DIV1 B43_LP_RADIO(0x0A7) /* LOGEN DIV 1 */
#define B2063_LOGEN_DIV2 B43_LP_RADIO(0x0A8) /* LOGEN DIV 2 */
#define B2063_LOGEN_DIV3 B43_LP_RADIO(0x0A9) /* LOGEN DIV 3 */
#define B2063_LOGEN_CBUFRX1 B43_LP_RADIO(0x0AA) /* LOGEN CBUFRX 1 */
#define B2063_LOGEN_CBUFRX2 B43_LP_RADIO(0x0AB) /* LOGEN CBUFRX 2 */
#define B2063_LOGEN_CBUFTX1 B43_LP_RADIO(0x0AC) /* LOGEN CBUFTX 1 */
#define B2063_LOGEN_CBUFTX2 B43_LP_RADIO(0x0AD) /* LOGEN CBUFTX 2 */
#define B2063_LOGEN_IDAC1 B43_LP_RADIO(0x0AE) /* LOGEN IDAC 1 */
#define B2063_LOGEN_SPARE1 B43_LP_RADIO(0x0AF) /* LOGEN SPARE 1 */
#define B2063_LOGEN_SPARE2 B43_LP_RADIO(0x0B0) /* LOGEN SPARE 2 */
#define B2063_LOGEN_SPARE3 B43_LP_RADIO(0x0B1) /* LOGEN SPARE 3 */
#define B2063_G_RX_1ST1 B43_LP_RADIO(0x0B2) /* G RX 1ST 1 */
#define B2063_G_RX_1ST2 B43_LP_RADIO(0x0B3) /* G RX 1ST 2 */
#define B2063_G_RX_1ST3 B43_LP_RADIO(0x0B4) /* G RX 1ST 3 */
#define B2063_G_RX_2ND1 B43_LP_RADIO(0x0B5) /* G RX 2ND 1 */
#define B2063_G_RX_2ND2 B43_LP_RADIO(0x0B6) /* G RX 2ND 2 */
#define B2063_G_RX_2ND3 B43_LP_RADIO(0x0B7) /* G RX 2ND 3 */
#define B2063_G_RX_2ND4 B43_LP_RADIO(0x0B8) /* G RX 2ND 4 */
#define B2063_G_RX_2ND5 B43_LP_RADIO(0x0B9) /* G RX 2ND 5 */
#define B2063_G_RX_2ND6 B43_LP_RADIO(0x0BA) /* G RX 2ND 6 */
#define B2063_G_RX_2ND7 B43_LP_RADIO(0x0BB) /* G RX 2ND 7 */
#define B2063_G_RX_2ND8 B43_LP_RADIO(0x0BC) /* G RX 2ND 8 */
#define B2063_G_RX_PS1 B43_LP_RADIO(0x0BD) /* G RX PS 1 */
#define B2063_G_RX_PS2 B43_LP_RADIO(0x0BE) /* G RX PS 2 */
#define B2063_G_RX_PS3 B43_LP_RADIO(0x0BF) /* G RX PS 3 */
#define B2063_G_RX_PS4 B43_LP_RADIO(0x0C0) /* G RX PS 4 */
#define B2063_G_RX_PS5 B43_LP_RADIO(0x0C1) /* G RX PS 5 */
#define B2063_G_RX_MIX1 B43_LP_RADIO(0x0C2) /* G RX MIX 1 */
#define B2063_G_RX_MIX2 B43_LP_RADIO(0x0C3) /* G RX MIX 2 */
#define B2063_G_RX_MIX3 B43_LP_RADIO(0x0C4) /* G RX MIX 3 */
#define B2063_G_RX_MIX4 B43_LP_RADIO(0x0C5) /* G RX MIX 4 */
#define B2063_G_RX_MIX5 B43_LP_RADIO(0x0C6) /* G RX MIX 5 */
#define B2063_G_RX_MIX6 B43_LP_RADIO(0x0C7) /* G RX MIX 6 */
#define B2063_G_RX_MIX7 B43_LP_RADIO(0x0C8) /* G RX MIX 7 */
#define B2063_G_RX_MIX8 B43_LP_RADIO(0x0C9) /* G RX MIX 8 */
#define B2063_G_RX_PDET1 B43_LP_RADIO(0x0CA) /* G RX PDET 1 */
#define B2063_G_RX_SPARES1 B43_LP_RADIO(0x0CB) /* G RX SPARES 1 */
#define B2063_G_RX_SPARES2 B43_LP_RADIO(0x0CC) /* G RX SPARES 2 */
#define B2063_G_RX_SPARES3 B43_LP_RADIO(0x0CD) /* G RX SPARES 3 */
#define B2063_A_RX_1ST1 B43_LP_RADIO(0x0CE) /* A RX 1ST 1 */
#define B2063_A_RX_1ST2 B43_LP_RADIO(0x0CF) /* A RX 1ST 2 */
#define B2063_A_RX_1ST3 B43_LP_RADIO(0x0D0) /* A RX 1ST 3 */
#define B2063_A_RX_1ST4 B43_LP_RADIO(0x0D1) /* A RX 1ST 4 */
#define B2063_A_RX_1ST5 B43_LP_RADIO(0x0D2) /* A RX 1ST 5 */
#define B2063_A_RX_2ND1 B43_LP_RADIO(0x0D3) /* A RX 2ND 1 */
#define B2063_A_RX_2ND2 B43_LP_RADIO(0x0D4) /* A RX 2ND 2 */
#define B2063_A_RX_2ND3 B43_LP_RADIO(0x0D5) /* A RX 2ND 3 */
#define B2063_A_RX_2ND4 B43_LP_RADIO(0x0D6) /* A RX 2ND 4 */
#define B2063_A_RX_2ND5 B43_LP_RADIO(0x0D7) /* A RX 2ND 5 */
#define B2063_A_RX_2ND6 B43_LP_RADIO(0x0D8) /* A RX 2ND 6 */
#define B2063_A_RX_2ND7 B43_LP_RADIO(0x0D9) /* A RX 2ND 7 */
#define B2063_A_RX_PS1 B43_LP_RADIO(0x0DA) /* A RX PS 1 */
#define B2063_A_RX_PS2 B43_LP_RADIO(0x0DB) /* A RX PS 2 */
#define B2063_A_RX_PS3 B43_LP_RADIO(0x0DC) /* A RX PS 3 */
#define B2063_A_RX_PS4 B43_LP_RADIO(0x0DD) /* A RX PS 4 */
#define B2063_A_RX_PS5 B43_LP_RADIO(0x0DE) /* A RX PS 5 */
#define B2063_A_RX_PS6 B43_LP_RADIO(0x0DF) /* A RX PS 6 */
#define B2063_A_RX_MIX1 B43_LP_RADIO(0x0E0) /* A RX MIX 1 */
#define B2063_A_RX_MIX2 B43_LP_RADIO(0x0E1) /* A RX MIX 2 */
#define B2063_A_RX_MIX3 B43_LP_RADIO(0x0E2) /* A RX MIX 3 */
#define B2063_A_RX_MIX4 B43_LP_RADIO(0x0E3) /* A RX MIX 4 */
#define B2063_A_RX_MIX5 B43_LP_RADIO(0x0E4) /* A RX MIX 5 */
#define B2063_A_RX_MIX6 B43_LP_RADIO(0x0E5) /* A RX MIX 6 */
#define B2063_A_RX_MIX7 B43_LP_RADIO(0x0E6) /* A RX MIX 7 */
#define B2063_A_RX_MIX8 B43_LP_RADIO(0x0E7) /* A RX MIX 8 */
#define B2063_A_RX_PWRDET1 B43_LP_RADIO(0x0E8) /* A RX PWRDET 1 */
#define B2063_A_RX_SPARE1 B43_LP_RADIO(0x0E9) /* A RX SPARE 1 */
#define B2063_A_RX_SPARE2 B43_LP_RADIO(0x0EA) /* A RX SPARE 2 */
#define B2063_A_RX_SPARE3 B43_LP_RADIO(0x0EB) /* A RX SPARE 3 */
#define B2063_RX_TIA_CTL1 B43_LP_RADIO(0x0EC) /* RX TIA Control 1 */
#define B2063_RX_TIA_CTL2 B43_LP_RADIO(0x0ED) /* RX TIA Control 2 */
#define B2063_RX_TIA_CTL3 B43_LP_RADIO(0x0EE) /* RX TIA Control 3 */
#define B2063_RX_TIA_CTL4 B43_LP_RADIO(0x0EF) /* RX TIA Control 4 */
#define B2063_RX_TIA_CTL5 B43_LP_RADIO(0x0F0) /* RX TIA Control 5 */
#define B2063_RX_TIA_CTL6 B43_LP_RADIO(0x0F1) /* RX TIA Control 6 */
#define B2063_RX_BB_CTL1 B43_LP_RADIO(0x0F2) /* RX BB Control 1 */
#define B2063_RX_BB_CTL2 B43_LP_RADIO(0x0F3) /* RX BB Control 2 */
#define B2063_RX_BB_CTL3 B43_LP_RADIO(0x0F4) /* RX BB Control 3 */
#define B2063_RX_BB_CTL4 B43_LP_RADIO(0x0F5) /* RX BB Control 4 */
#define B2063_RX_BB_CTL5 B43_LP_RADIO(0x0F6) /* RX BB Control 5 */
#define B2063_RX_BB_CTL6 B43_LP_RADIO(0x0F7) /* RX BB Control 6 */
#define B2063_RX_BB_CTL7 B43_LP_RADIO(0x0F8) /* RX BB Control 7 */
#define B2063_RX_BB_CTL8 B43_LP_RADIO(0x0F9) /* RX BB Control 8 */
#define B2063_RX_BB_CTL9 B43_LP_RADIO(0x0FA) /* RX BB Control 9 */
#define B2063_TX_RF_CTL1 B43_LP_RADIO(0x0FB) /* TX RF Control 1 */
#define B2063_TX_RF_IDAC_LO_RF_I B43_LP_RADIO(0x0FC) /* TX RF IDAC LO RF I */
#define B2063_TX_RF_IDAC_LO_RF_Q B43_LP_RADIO(0x0FD) /* TX RF IDAC LO RF Q */
#define B2063_TX_RF_IDAC_LO_BB_I B43_LP_RADIO(0x0FE) /* TX RF IDAC LO BB I */
#define B2063_TX_RF_IDAC_LO_BB_Q B43_LP_RADIO(0x0FF) /* TX RF IDAC LO BB Q */
#define B2063_TX_RF_CTL2 B43_LP_RADIO(0x100) /* TX RF Control 2 */
#define B2063_TX_RF_CTL3 B43_LP_RADIO(0x101) /* TX RF Control 3 */
#define B2063_TX_RF_CTL4 B43_LP_RADIO(0x102) /* TX RF Control 4 */
#define B2063_TX_RF_CTL5 B43_LP_RADIO(0x103) /* TX RF Control 5 */
#define B2063_TX_RF_CTL6 B43_LP_RADIO(0x104) /* TX RF Control 6 */
#define B2063_TX_RF_CTL7 B43_LP_RADIO(0x105) /* TX RF Control 7 */
#define B2063_TX_RF_CTL8 B43_LP_RADIO(0x106) /* TX RF Control 8 */
#define B2063_TX_RF_CTL9 B43_LP_RADIO(0x107) /* TX RF Control 9 */
#define B2063_TX_RF_CTL10 B43_LP_RADIO(0x108) /* TX RF Control 10 */
#define B2063_TX_RF_CTL14 B43_LP_RADIO(0x109) /* TX RF Control 14 */
#define B2063_TX_RF_CTL15 B43_LP_RADIO(0x10A) /* TX RF Control 15 */
#define B2063_PA_CTL1 B43_LP_RADIO(0x10B) /* PA Control 1 */
#define B2063_PA_CTL2 B43_LP_RADIO(0x10C) /* PA Control 2 */
#define B2063_PA_CTL3 B43_LP_RADIO(0x10D) /* PA Control 3 */
#define B2063_PA_CTL4 B43_LP_RADIO(0x10E) /* PA Control 4 */
#define B2063_PA_CTL5 B43_LP_RADIO(0x10F) /* PA Control 5 */
#define B2063_PA_CTL6 B43_LP_RADIO(0x110) /* PA Control 6 */
#define B2063_PA_CTL7 B43_LP_RADIO(0x111) /* PA Control 7 */
#define B2063_PA_CTL8 B43_LP_RADIO(0x112) /* PA Control 8 */
#define B2063_PA_CTL9 B43_LP_RADIO(0x113) /* PA Control 9 */
#define B2063_PA_CTL10 B43_LP_RADIO(0x114) /* PA Control 10 */
#define B2063_PA_CTL11 B43_LP_RADIO(0x115) /* PA Control 11 */
#define B2063_PA_CTL12 B43_LP_RADIO(0x116) /* PA Control 12 */
#define B2063_PA_CTL13 B43_LP_RADIO(0x117) /* PA Control 13 */
#define B2063_TX_BB_CTL1 B43_LP_RADIO(0x118) /* TX BB Control 1 */
#define B2063_TX_BB_CTL2 B43_LP_RADIO(0x119) /* TX BB Control 2 */
#define B2063_TX_BB_CTL3 B43_LP_RADIO(0x11A) /* TX BB Control 3 */
#define B2063_TX_BB_CTL4 B43_LP_RADIO(0x11B) /* TX BB Control 4 */
#define B2063_GPIO_CTL1 B43_LP_RADIO(0x11C) /* GPIO Control 1 */
#define B2063_VREG_CTL1 B43_LP_RADIO(0x11D) /* VREG Control 1 */
#define B2063_AMUX_CTL1 B43_LP_RADIO(0x11E) /* AMUX Control 1 */
#define B2063_IQ_CALIB_GVAR B43_LP_RADIO(0x11F) /* IQ Calibration GVAR */
#define B2063_IQ_CALIB_CTL1 B43_LP_RADIO(0x120) /* IQ Calibration Control 1 */
#define B2063_IQ_CALIB_CTL2 B43_LP_RADIO(0x121) /* IQ Calibration Control 2 */
#define B2063_TEMPSENSE_CTL1 B43_LP_RADIO(0x122) /* TEMPSENSE Control 1 */
#define B2063_TEMPSENSE_CTL2 B43_LP_RADIO(0x123) /* TEMPSENSE Control 2 */
#define B2063_TX_RX_LOOPBACK1 B43_LP_RADIO(0x124) /* TX/RX LOOPBACK 1 */
#define B2063_TX_RX_LOOPBACK2 B43_LP_RADIO(0x125) /* TX/RX LOOPBACK 2 */
#define B2063_EXT_TSSI_CTL1 B43_LP_RADIO(0x126) /* EXT TSSI Control 1 */
#define B2063_EXT_TSSI_CTL2 B43_LP_RADIO(0x127) /* EXT TSSI Control 2 */
#define B2063_AFE_CTL B43_LP_RADIO(0x128) /* AFE Control */
enum b43_lpphy_txpctl_mode {
B43_LPPHY_TXPCTL_UNKNOWN = 0,
B43_LPPHY_TXPCTL_OFF, /* TX power control is OFF */
B43_LPPHY_TXPCTL_SW, /* TX power control is set to Software */
B43_LPPHY_TXPCTL_HW, /* TX power control is set to Hardware */
};
struct b43_phy_lp {
/* Current TX power control mode. */
enum b43_lpphy_txpctl_mode txpctl_mode;
/* Transmit isolation medium band */
u8 tx_isolation_med_band;
/* Transmit isolation low band */
u8 tx_isolation_low_band;
/* Transmit isolation high band */
u8 tx_isolation_hi_band;
/* Max transmit power medium band */
u16 max_tx_pwr_med_band;
/* Max transmit power low band */
u16 max_tx_pwr_low_band;
/* Max transmit power high band */
u16 max_tx_pwr_hi_band;
/* FIXME What are these used for? */
/* FIXME Is 15 the correct array size? */
u16 tx_max_rate[15];
u16 tx_max_ratel[15];
u16 tx_max_rateh[15];
/* Transmit power arrays */
s16 txpa[3], txpal[3], txpah[3];
/* Receive power offset */
u8 rx_pwr_offset;
/* TSSI transmit count */
u16 tssi_tx_count;
/* TSSI index */
u16 tssi_idx; /* FIXME initial value? */
/* TSSI npt */
u16 tssi_npt; /* FIXME initial value? */
/* Target TX frequency */
u16 tgt_tx_freq; /* FIXME initial value? */
/* Transmit power index override */
s8 tx_pwr_idx_over; /* FIXME initial value? */
/* RSSI vf */
u8 rssi_vf;
/* RSSI vc */
u8 rssi_vc;
/* RSSI gs */
u8 rssi_gs;
/* RC cap */
u8 rc_cap;
/* BX arch */
u8 bx_arch;
/* Full calibration channel */
u8 full_calib_chan;
/* Transmit iqlocal best coeffs */
bool tx_iqloc_best_coeffs_valid;
u8 tx_iqloc_best_coeffs[11];
/* Used for "Save/Restore Dig Filt State" */
u16 dig_flt_state[9];
bool crs_usr_disable, crs_sys_disable;
unsigned int pdiv;
/* The channel we are tuned to */
u8 channel;
/* The active antenna diversity mode */
int antenna;
/* Frequency of the active TX tone */
int tx_tone_freq;
};
enum tssi_mux_mode {
TSSI_MUX_PREPA,
TSSI_MUX_POSTPA,
TSSI_MUX_EXT,
};
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lp;
#endif /* LINUX_B43_PHY_LP_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,834 @@
/*
Broadcom B43 wireless driver
PIO data transfer
Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
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 "pio.h"
#include "dma.h"
#include "main.h"
#include "xmit.h"
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
static u16 generate_cookie(struct b43_pio_txqueue *q,
struct b43_pio_txpacket *pack)
{
u16 cookie;
/* Use the upper 4 bits of the cookie as
* PIO controller ID and store the packet index number
* in the lower 12 bits.
* Note that the cookie must never be 0, as this
* is a special value used in RX path.
* It can also not be 0xFFFF because that is special
* for multicast frames.
*/
cookie = (((u16)q->index + 1) << 12);
cookie |= pack->index;
return cookie;
}
static
struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
u16 cookie,
struct b43_pio_txpacket **pack)
{
struct b43_pio *pio = &dev->pio;
struct b43_pio_txqueue *q = NULL;
unsigned int pack_index;
switch (cookie & 0xF000) {
case 0x1000:
q = pio->tx_queue_AC_BK;
break;
case 0x2000:
q = pio->tx_queue_AC_BE;
break;
case 0x3000:
q = pio->tx_queue_AC_VI;
break;
case 0x4000:
q = pio->tx_queue_AC_VO;
break;
case 0x5000:
q = pio->tx_queue_mcast;
break;
}
if (B43_WARN_ON(!q))
return NULL;
pack_index = (cookie & 0x0FFF);
if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
return NULL;
*pack = &q->packets[pack_index];
return q;
}
static u16 index_to_pioqueue_base(struct b43_wldev *dev,
unsigned int index)
{
static const u16 bases[] = {
B43_MMIO_PIO_BASE0,
B43_MMIO_PIO_BASE1,
B43_MMIO_PIO_BASE2,
B43_MMIO_PIO_BASE3,
B43_MMIO_PIO_BASE4,
B43_MMIO_PIO_BASE5,
B43_MMIO_PIO_BASE6,
B43_MMIO_PIO_BASE7,
};
static const u16 bases_rev11[] = {
B43_MMIO_PIO11_BASE0,
B43_MMIO_PIO11_BASE1,
B43_MMIO_PIO11_BASE2,
B43_MMIO_PIO11_BASE3,
B43_MMIO_PIO11_BASE4,
B43_MMIO_PIO11_BASE5,
};
if (dev->dev->core_rev >= 11) {
B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
return bases_rev11[index];
}
B43_WARN_ON(index >= ARRAY_SIZE(bases));
return bases[index];
}
static u16 pio_txqueue_offset(struct b43_wldev *dev)
{
if (dev->dev->core_rev >= 11)
return 0x18;
return 0;
}
static u16 pio_rxqueue_offset(struct b43_wldev *dev)
{
if (dev->dev->core_rev >= 11)
return 0x38;
return 8;
}
static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
unsigned int index)
{
struct b43_pio_txqueue *q;
struct b43_pio_txpacket *p;
unsigned int i;
q = kzalloc(sizeof(*q), GFP_KERNEL);
if (!q)
return NULL;
q->dev = dev;
q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_txqueue_offset(dev);
q->index = index;
q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
if (q->rev >= 8) {
q->buffer_size = 1920; //FIXME this constant is wrong.
} else {
q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
q->buffer_size -= 80;
}
INIT_LIST_HEAD(&q->packets_list);
for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
p = &(q->packets[i]);
INIT_LIST_HEAD(&p->list);
p->index = i;
p->queue = q;
list_add(&p->list, &q->packets_list);
}
return q;
}
static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
unsigned int index)
{
struct b43_pio_rxqueue *q;
q = kzalloc(sizeof(*q), GFP_KERNEL);
if (!q)
return NULL;
q->dev = dev;
q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
/* Enable Direct FIFO RX (PIO) on the engine. */
b43_dma_direct_fifo_rx(dev, index, 1);
return q;
}
static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
{
struct b43_pio_txpacket *pack;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
pack = &(q->packets[i]);
if (pack->skb) {
ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
pack->skb = NULL;
}
}
}
static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
const char *name)
{
if (!q)
return;
b43_pio_cancel_tx_packets(q);
kfree(q);
}
static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
const char *name)
{
if (!q)
return;
kfree(q);
}
#define destroy_queue_tx(pio, queue) do { \
b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
(pio)->queue = NULL; \
} while (0)
#define destroy_queue_rx(pio, queue) do { \
b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
(pio)->queue = NULL; \
} while (0)
void b43_pio_free(struct b43_wldev *dev)
{
struct b43_pio *pio;
if (!b43_using_pio_transfers(dev))
return;
pio = &dev->pio;
destroy_queue_rx(pio, rx_queue);
destroy_queue_tx(pio, tx_queue_mcast);
destroy_queue_tx(pio, tx_queue_AC_VO);
destroy_queue_tx(pio, tx_queue_AC_VI);
destroy_queue_tx(pio, tx_queue_AC_BE);
destroy_queue_tx(pio, tx_queue_AC_BK);
}
int b43_pio_init(struct b43_wldev *dev)
{
struct b43_pio *pio = &dev->pio;
int err = -ENOMEM;
b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
& ~B43_MACCTL_BE);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
if (!pio->tx_queue_AC_BK)
goto out;
pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
if (!pio->tx_queue_AC_BE)
goto err_destroy_bk;
pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
if (!pio->tx_queue_AC_VI)
goto err_destroy_be;
pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
if (!pio->tx_queue_AC_VO)
goto err_destroy_vi;
pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
if (!pio->tx_queue_mcast)
goto err_destroy_vo;
pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
if (!pio->rx_queue)
goto err_destroy_mcast;
b43dbg(dev->wl, "PIO initialized\n");
err = 0;
out:
return err;
err_destroy_mcast:
destroy_queue_tx(pio, tx_queue_mcast);
err_destroy_vo:
destroy_queue_tx(pio, tx_queue_AC_VO);
err_destroy_vi:
destroy_queue_tx(pio, tx_queue_AC_VI);
err_destroy_be:
destroy_queue_tx(pio, tx_queue_AC_BE);
err_destroy_bk:
destroy_queue_tx(pio, tx_queue_AC_BK);
return err;
}
/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
u8 queue_prio)
{
struct b43_pio_txqueue *q;
if (dev->qos_enabled) {
/* 0 = highest priority */
switch (queue_prio) {
default:
B43_WARN_ON(1);
/* fallthrough */
case 0:
q = dev->pio.tx_queue_AC_VO;
break;
case 1:
q = dev->pio.tx_queue_AC_VI;
break;
case 2:
q = dev->pio.tx_queue_AC_BE;
break;
case 3:
q = dev->pio.tx_queue_AC_BK;
break;
}
} else
q = dev->pio.tx_queue_AC_BE;
return q;
}
static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
u16 ctl,
const void *_data,
unsigned int data_len)
{
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
const u8 *data = _data;
ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
b43_block_write(dev, data, (data_len & ~1),
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
if (data_len & 1) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
/* Write the last byte. */
ctl &= ~B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
tail[0] = data[data_len - 1];
tail[1] = 0;
b43_block_write(dev, tail, 2,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
}
return ctl;
}
static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
const u8 *hdr, unsigned int hdrlen)
{
struct b43_pio_txqueue *q = pack->queue;
const char *frame = pack->skb->data;
unsigned int frame_len = pack->skb->len;
u16 ctl;
ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
ctl |= B43_PIO_TXCTL_FREADY;
ctl &= ~B43_PIO_TXCTL_EOF;
/* Transfer the header data. */
ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
/* Transfer the frame data. */
ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO_TXCTL_EOF;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
}
static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
u32 ctl,
const void *_data,
unsigned int data_len)
{
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
const u8 *data = _data;
ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
b43_block_write(dev, data, (data_len & ~3),
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
if (data_len & 3) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
memset(tail, 0, 4);
/* Write the last few bytes. */
ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
B43_PIO8_TXCTL_24_31);
switch (data_len & 3) {
case 3:
ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
tail[0] = data[data_len - 3];
tail[1] = data[data_len - 2];
tail[2] = data[data_len - 1];
break;
case 2:
ctl |= B43_PIO8_TXCTL_8_15;
tail[0] = data[data_len - 2];
tail[1] = data[data_len - 1];
break;
case 1:
tail[0] = data[data_len - 1];
break;
}
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
b43_block_write(dev, tail, 4,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
}
return ctl;
}
static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
const u8 *hdr, unsigned int hdrlen)
{
struct b43_pio_txqueue *q = pack->queue;
const char *frame = pack->skb->data;
unsigned int frame_len = pack->skb->len;
u32 ctl;
ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
ctl |= B43_PIO8_TXCTL_FREADY;
ctl &= ~B43_PIO8_TXCTL_EOF;
/* Transfer the header data. */
ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
/* Transfer the frame data. */
ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO8_TXCTL_EOF;
b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
}
static int pio_tx_frame(struct b43_pio_txqueue *q,
struct sk_buff *skb)
{
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
struct b43_pio_txpacket *pack;
u16 cookie;
int err;
unsigned int hdrlen;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
B43_WARN_ON(list_empty(&q->packets_list));
pack = list_entry(q->packets_list.next,
struct b43_pio_txpacket, list);
cookie = generate_cookie(q, pack);
hdrlen = b43_txhdr_size(dev);
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
info, cookie);
if (err)
return err;
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
/* Tell the firmware about the cookie of the last
* mcast frame, so it can clear the more-data bit in it. */
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_MCASTCOOKIE, cookie);
}
pack->skb = skb;
if (q->rev >= 8)
pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
else
pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
/* Remove it from the list of available packet slots.
* It will be put back when we receive the status report. */
list_del(&pack->list);
/* Update the queue statistics. */
q->buffer_used += roundup(skb->len + hdrlen, 4);
q->free_packet_slots -= 1;
return 0;
}
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
{
struct b43_pio_txqueue *q;
struct ieee80211_hdr *hdr;
unsigned int hdrlen, total_len;
int err = 0;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
hdr = (struct ieee80211_hdr *)skb->data;
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
/* The multicast queue will be sent after the DTIM. */
q = dev->pio.tx_queue_mcast;
/* Set the frame More-Data bit. Ucode will clear it
* for us on the last frame. */
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
} else {
/* Decide by priority where to put this frame. */
q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
}
hdrlen = b43_txhdr_size(dev);
total_len = roundup(skb->len + hdrlen, 4);
if (unlikely(total_len > q->buffer_size)) {
err = -ENOBUFS;
b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
goto out;
}
if (unlikely(q->free_packet_slots == 0)) {
err = -ENOBUFS;
b43warn(dev->wl, "PIO: TX packet overflow.\n");
goto out;
}
B43_WARN_ON(q->buffer_used > q->buffer_size);
if (total_len > (q->buffer_size - q->buffer_used)) {
/* Not enough memory on the queue. */
err = -EBUSY;
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
q->stopped = true;
goto out;
}
/* Assign the queue number to the ring (if not already done before)
* so TX status handling can use it. The mac80211-queue to b43-queue
* mapping is static, so we don't need to store it per frame. */
q->queue_prio = skb_get_queue_mapping(skb);
err = pio_tx_frame(q, skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
ieee80211_free_txskb(dev->wl->hw, skb);
err = 0;
goto out;
}
if (unlikely(err)) {
b43err(dev->wl, "PIO transmission failure\n");
goto out;
}
B43_WARN_ON(q->buffer_used > q->buffer_size);
if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
(q->free_packet_slots == 0)) {
/* The queue is full. */
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
q->stopped = true;
}
out:
return err;
}
void b43_pio_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
struct b43_pio_txqueue *q;
struct b43_pio_txpacket *pack = NULL;
unsigned int total_len;
struct ieee80211_tx_info *info;
q = parse_cookie(dev, status->cookie, &pack);
if (unlikely(!q))
return;
B43_WARN_ON(!pack);
info = IEEE80211_SKB_CB(pack->skb);
b43_fill_txstatus_report(dev, info, status);
total_len = pack->skb->len + b43_txhdr_size(dev);
total_len = roundup(total_len, 4);
q->buffer_used -= total_len;
q->free_packet_slots += 1;
ieee80211_tx_status(dev->wl->hw, pack->skb);
pack->skb = NULL;
list_add(&pack->list, &q->packets_list);
if (q->stopped) {
ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
q->stopped = false;
}
}
/* Returns whether we should fetch another frame. */
static bool pio_rx_frame(struct b43_pio_rxqueue *q)
{
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
u16 len;
u32 macstat = 0;
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
struct b43_rxhdr_fw4 *rxhdr =
(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
size_t rxhdr_size = sizeof(*rxhdr);
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
switch (dev->fw.hdr_format) {
case B43_FW_HDR_410:
case B43_FW_HDR_351:
rxhdr_size -= sizeof(rxhdr->format_598) -
sizeof(rxhdr->format_351);
break;
case B43_FW_HDR_598:
break;
}
memset(rxhdr, 0, rxhdr_size);
/* Check if we have data and wait for it to get ready. */
if (q->rev >= 8) {
u32 ctl;
ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
return false;
b43_piorx_write32(q, B43_PIO8_RXCTL,
B43_PIO8_RXCTL_FRAMERDY);
for (i = 0; i < 10; i++) {
ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
if (ctl & B43_PIO8_RXCTL_DATARDY)
goto data_ready;
udelay(10);
}
} else {
u16 ctl;
ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
return false;
b43_piorx_write16(q, B43_PIO_RXCTL,
B43_PIO_RXCTL_FRAMERDY);
for (i = 0; i < 10; i++) {
ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
if (ctl & B43_PIO_RXCTL_DATARDY)
goto data_ready;
udelay(10);
}
}
b43dbg(q->dev->wl, "PIO RX timed out\n");
return true;
data_ready:
/* Get the preamble (RX header) */
if (q->rev >= 8) {
b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
} else {
b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
}
/* Sanity checks. */
len = le16_to_cpu(rxhdr->frame_len);
if (unlikely(len > 0x700)) {
err_msg = "len > 0x700";
goto rx_error;
}
if (unlikely(len == 0)) {
err_msg = "len == 0";
goto rx_error;
}
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
macstat = le32_to_cpu(rxhdr->format_598.mac_status);
break;
case B43_FW_HDR_410:
case B43_FW_HDR_351:
macstat = le32_to_cpu(rxhdr->format_351.mac_status);
break;
}
if (macstat & B43_RX_MAC_FCSERR) {
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
/* Drop frames with failed FCS. */
err_msg = "Frame FCS error";
goto rx_error;
}
}
/* We always pad 2 bytes, as that's what upstream code expects
* due to the RX-header being 30 bytes. In case the frame is
* unaligned, we pad another 2 bytes. */
padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
skb = dev_alloc_skb(len + padding + 2);
if (unlikely(!skb)) {
err_msg = "Out of memory";
goto rx_error;
}
skb_reserve(skb, 2);
skb_put(skb, len + padding);
if (q->rev >= 8) {
b43_block_read(dev, skb->data + padding, (len & ~3),
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
if (len & 3) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
/* Read the last few bytes. */
b43_block_read(dev, tail, 4,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
switch (len & 3) {
case 3:
skb->data[len + padding - 3] = tail[0];
skb->data[len + padding - 2] = tail[1];
skb->data[len + padding - 1] = tail[2];
break;
case 2:
skb->data[len + padding - 2] = tail[0];
skb->data[len + padding - 1] = tail[1];
break;
case 1:
skb->data[len + padding - 1] = tail[0];
break;
}
}
} else {
b43_block_read(dev, skb->data + padding, (len & ~1),
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
u8 *tail = wl->pio_tailspace;
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
/* Read the last byte. */
b43_block_read(dev, tail, 2,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
skb->data[len + padding - 1] = tail[0];
}
}
b43_rx(q->dev, skb, rxhdr);
return true;
rx_error:
if (err_msg)
b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
if (q->rev >= 8)
b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
else
b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
return true;
}
void b43_pio_rx(struct b43_pio_rxqueue *q)
{
unsigned int count = 0;
bool stop;
while (1) {
stop = (pio_rx_frame(q) == 0);
if (stop)
break;
cond_resched();
if (WARN_ON_ONCE(++count > 10000))
break;
}
}
static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
{
if (q->rev >= 8) {
b43_piotx_write32(q, B43_PIO8_TXCTL,
b43_piotx_read32(q, B43_PIO8_TXCTL)
| B43_PIO8_TXCTL_SUSPREQ);
} else {
b43_piotx_write16(q, B43_PIO_TXCTL,
b43_piotx_read16(q, B43_PIO_TXCTL)
| B43_PIO_TXCTL_SUSPREQ);
}
}
static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
{
if (q->rev >= 8) {
b43_piotx_write32(q, B43_PIO8_TXCTL,
b43_piotx_read32(q, B43_PIO8_TXCTL)
& ~B43_PIO8_TXCTL_SUSPREQ);
} else {
b43_piotx_write16(q, B43_PIO_TXCTL,
b43_piotx_read16(q, B43_PIO_TXCTL)
& ~B43_PIO_TXCTL_SUSPREQ);
}
}
void b43_pio_tx_suspend(struct b43_wldev *dev)
{
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
}
void b43_pio_tx_resume(struct b43_wldev *dev)
{
b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
b43_power_saving_ctl_bits(dev, 0);
}

View File

@@ -0,0 +1,165 @@
#ifndef B43_PIO_H_
#define B43_PIO_H_
#include "b43.h"
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/skbuff.h>
/*** Registers for PIO queues up to revision 7. ***/
/* TX queue. */
#define B43_PIO_TXCTL 0x00
#define B43_PIO_TXCTL_WRITELO 0x0001
#define B43_PIO_TXCTL_WRITEHI 0x0002
#define B43_PIO_TXCTL_EOF 0x0004
#define B43_PIO_TXCTL_FREADY 0x0008
#define B43_PIO_TXCTL_FLUSHREQ 0x0020
#define B43_PIO_TXCTL_FLUSHPEND 0x0040
#define B43_PIO_TXCTL_SUSPREQ 0x0080
#define B43_PIO_TXCTL_QSUSP 0x0100
#define B43_PIO_TXCTL_COMMCNT 0xFC00
#define B43_PIO_TXCTL_COMMCNT_SHIFT 10
#define B43_PIO_TXDATA 0x02
#define B43_PIO_TXQBUFSIZE 0x04
/* RX queue. */
#define B43_PIO_RXCTL 0x00
#define B43_PIO_RXCTL_FRAMERDY 0x0001
#define B43_PIO_RXCTL_DATARDY 0x0002
#define B43_PIO_RXDATA 0x02
/*** Registers for PIO queues revision 8 and later. ***/
/* TX queue */
#define B43_PIO8_TXCTL 0x00
#define B43_PIO8_TXCTL_0_7 0x00000001
#define B43_PIO8_TXCTL_8_15 0x00000002
#define B43_PIO8_TXCTL_16_23 0x00000004
#define B43_PIO8_TXCTL_24_31 0x00000008
#define B43_PIO8_TXCTL_EOF 0x00000010
#define B43_PIO8_TXCTL_FREADY 0x00000080
#define B43_PIO8_TXCTL_SUSPREQ 0x00000100
#define B43_PIO8_TXCTL_QSUSP 0x00000200
#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400
#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800
#define B43_PIO8_TXDATA 0x04
/* RX queue */
#define B43_PIO8_RXCTL 0x00
#define B43_PIO8_RXCTL_FRAMERDY 0x00000001
#define B43_PIO8_RXCTL_DATARDY 0x00000002
#define B43_PIO8_RXDATA 0x04
/* The maximum number of TX-packets the HW can handle. */
#define B43_PIO_MAX_NR_TXPACKETS 32
struct b43_pio_txpacket {
/* Pointer to the TX queue we belong to. */
struct b43_pio_txqueue *queue;
/* The TX data packet. */
struct sk_buff *skb;
/* Index in the (struct b43_pio_txqueue)->packets array. */
u8 index;
struct list_head list;
};
struct b43_pio_txqueue {
struct b43_wldev *dev;
u16 mmio_base;
/* The device queue buffer size in bytes. */
u16 buffer_size;
/* The number of used bytes in the device queue buffer. */
u16 buffer_used;
/* The number of packets that can still get queued.
* This is decremented on queueing a packet and incremented
* after receiving the transmit status. */
u16 free_packet_slots;
/* True, if the mac80211 queue was stopped due to overflow at TX. */
bool stopped;
/* Our b43 queue index number */
u8 index;
/* The mac80211 QoS queue priority. */
u8 queue_prio;
/* Buffer for TX packet meta data. */
struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
struct list_head packets_list;
/* Shortcut to the 802.11 core revision. This is to
* avoid horrible pointer dereferencing in the fastpaths. */
u8 rev;
};
struct b43_pio_rxqueue {
struct b43_wldev *dev;
u16 mmio_base;
/* Shortcut to the 802.11 core revision. This is to
* avoid horrible pointer dereferencing in the fastpaths. */
u8 rev;
};
static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
{
return b43_read16(q->dev, q->mmio_base + offset);
}
static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
{
return b43_read32(q->dev, q->mmio_base + offset);
}
static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
u16 offset, u16 value)
{
b43_write16(q->dev, q->mmio_base + offset, value);
}
static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
u16 offset, u32 value)
{
b43_write32(q->dev, q->mmio_base + offset, value);
}
static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
{
return b43_read16(q->dev, q->mmio_base + offset);
}
static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
{
return b43_read32(q->dev, q->mmio_base + offset);
}
static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
u16 offset, u16 value)
{
b43_write16(q->dev, q->mmio_base + offset, value);
}
static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
u16 offset, u32 value)
{
b43_write32(q->dev, q->mmio_base + offset, value);
}
int b43_pio_init(struct b43_wldev *dev);
void b43_pio_free(struct b43_wldev *dev);
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
void b43_pio_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
void b43_pio_rx(struct b43_pio_rxqueue *q);
void b43_pio_tx_suspend(struct b43_wldev *dev);
void b43_pio_tx_resume(struct b43_wldev *dev);
#endif /* B43_PIO_H_ */

View File

@@ -0,0 +1,199 @@
/*
* Broadcom B43 wireless driver
* PPR (Power Per Rate) management
*
* Copyright (c) 2014 Rafał Miłecki <zajec5@gmail.com>
*
* 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.
*/
#include "ppr.h"
#include "b43.h"
#define ppr_for_each_entry(ppr, i, entry) \
for (i = 0, entry = &(ppr)->__all_rates[i]; \
i < B43_PPR_RATES_NUM; \
i++, entry++)
void b43_ppr_clear(struct b43_wldev *dev, struct b43_ppr *ppr)
{
memset(ppr, 0, sizeof(*ppr));
/* Compile-time PPR check */
BUILD_BUG_ON(sizeof(struct b43_ppr) != B43_PPR_RATES_NUM * sizeof(u8));
}
void b43_ppr_add(struct b43_wldev *dev, struct b43_ppr *ppr, int diff)
{
int i;
u8 *rate;
ppr_for_each_entry(ppr, i, rate) {
*rate = clamp_val(*rate + diff, 0, 127);
}
}
void b43_ppr_apply_max(struct b43_wldev *dev, struct b43_ppr *ppr, u8 max)
{
int i;
u8 *rate;
ppr_for_each_entry(ppr, i, rate) {
*rate = min(*rate, max);
}
}
void b43_ppr_apply_min(struct b43_wldev *dev, struct b43_ppr *ppr, u8 min)
{
int i;
u8 *rate;
ppr_for_each_entry(ppr, i, rate) {
*rate = max(*rate, min);
}
}
u8 b43_ppr_get_max(struct b43_wldev *dev, struct b43_ppr *ppr)
{
u8 res = 0;
int i;
u8 *rate;
ppr_for_each_entry(ppr, i, rate) {
res = max(*rate, res);
}
return res;
}
bool b43_ppr_load_max_from_sprom(struct b43_wldev *dev, struct b43_ppr *ppr,
enum b43_band band)
{
struct b43_ppr_rates *rates = &ppr->rates;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
u8 maxpwr, off;
u32 sprom_ofdm_po;
u16 *sprom_mcs_po;
u8 extra_cdd_po, extra_stbc_po;
int i;
switch (band) {
case B43_BAND_2G:
maxpwr = min(sprom->core_pwr_info[0].maxpwr_2g,
sprom->core_pwr_info[1].maxpwr_2g);
sprom_ofdm_po = sprom->ofdm2gpo;
sprom_mcs_po = sprom->mcs2gpo;
extra_cdd_po = (sprom->cddpo >> 0) & 0xf;
extra_stbc_po = (sprom->stbcpo >> 0) & 0xf;
break;
case B43_BAND_5G_LO:
maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gl,
sprom->core_pwr_info[1].maxpwr_5gl);
sprom_ofdm_po = sprom->ofdm5glpo;
sprom_mcs_po = sprom->mcs5glpo;
extra_cdd_po = (sprom->cddpo >> 8) & 0xf;
extra_stbc_po = (sprom->stbcpo >> 8) & 0xf;
break;
case B43_BAND_5G_MI:
maxpwr = min(sprom->core_pwr_info[0].maxpwr_5g,
sprom->core_pwr_info[1].maxpwr_5g);
sprom_ofdm_po = sprom->ofdm5gpo;
sprom_mcs_po = sprom->mcs5gpo;
extra_cdd_po = (sprom->cddpo >> 4) & 0xf;
extra_stbc_po = (sprom->stbcpo >> 4) & 0xf;
break;
case B43_BAND_5G_HI:
maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gh,
sprom->core_pwr_info[1].maxpwr_5gh);
sprom_ofdm_po = sprom->ofdm5ghpo;
sprom_mcs_po = sprom->mcs5ghpo;
extra_cdd_po = (sprom->cddpo >> 12) & 0xf;
extra_stbc_po = (sprom->stbcpo >> 12) & 0xf;
break;
default:
WARN_ON_ONCE(1);
return false;
}
if (band == B43_BAND_2G) {
for (i = 0; i < 4; i++) {
off = ((sprom->cck2gpo >> (i * 4)) & 0xf) * 2;
rates->cck[i] = maxpwr - off;
}
}
/* OFDM */
for (i = 0; i < 8; i++) {
off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2;
rates->ofdm[i] = maxpwr - off;
}
/* MCS 20 SISO */
rates->mcs_20[0] = rates->ofdm[0];
rates->mcs_20[1] = rates->ofdm[2];
rates->mcs_20[2] = rates->ofdm[3];
rates->mcs_20[3] = rates->ofdm[4];
rates->mcs_20[4] = rates->ofdm[5];
rates->mcs_20[5] = rates->ofdm[6];
rates->mcs_20[6] = rates->ofdm[7];
rates->mcs_20[7] = rates->ofdm[7];
/* MCS 20 CDD */
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_cdd[i] = maxpwr - off;
if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
rates->mcs_20_cdd[i] -= extra_cdd_po;
}
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_cdd[4 + i] = maxpwr - off;
if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
rates->mcs_20_cdd[4 + i] -= extra_cdd_po;
}
/* OFDM 20 CDD */
rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0];
rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0];
rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1];
rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2];
rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3];
rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4];
rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5];
rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6];
/* MCS 20 STBC */
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_stbc[i] = maxpwr - off;
if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
rates->mcs_20_stbc[i] -= extra_stbc_po;
}
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_stbc[4 + i] = maxpwr - off;
if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
rates->mcs_20_stbc[4 + i] -= extra_stbc_po;
}
/* MCS 20 SDM */
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_sdm[i] = maxpwr - off;
}
for (i = 0; i < 4; i++) {
off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2;
rates->mcs_20_sdm[4 + i] = maxpwr - off;
}
return true;
}

View File

@@ -0,0 +1,45 @@
#ifndef LINUX_B43_PPR_H_
#define LINUX_B43_PPR_H_
#include <linux/types.h>
#define B43_PPR_CCK_RATES_NUM 4
#define B43_PPR_OFDM_RATES_NUM 8
#define B43_PPR_MCS_RATES_NUM 8
#define B43_PPR_RATES_NUM (B43_PPR_CCK_RATES_NUM + \
B43_PPR_OFDM_RATES_NUM * 2 + \
B43_PPR_MCS_RATES_NUM * 4)
struct b43_ppr_rates {
u8 cck[B43_PPR_CCK_RATES_NUM];
u8 ofdm[B43_PPR_OFDM_RATES_NUM];
u8 ofdm_20_cdd[B43_PPR_OFDM_RATES_NUM];
u8 mcs_20[B43_PPR_MCS_RATES_NUM]; /* SISO */
u8 mcs_20_cdd[B43_PPR_MCS_RATES_NUM];
u8 mcs_20_stbc[B43_PPR_MCS_RATES_NUM];
u8 mcs_20_sdm[B43_PPR_MCS_RATES_NUM];
};
struct b43_ppr {
/* All powers are in qdbm (Q5.2) */
union {
u8 __all_rates[B43_PPR_RATES_NUM];
struct b43_ppr_rates rates;
};
};
struct b43_wldev;
enum b43_band;
void b43_ppr_clear(struct b43_wldev *dev, struct b43_ppr *ppr);
void b43_ppr_add(struct b43_wldev *dev, struct b43_ppr *ppr, int diff);
void b43_ppr_apply_max(struct b43_wldev *dev, struct b43_ppr *ppr, u8 max);
void b43_ppr_apply_min(struct b43_wldev *dev, struct b43_ppr *ppr, u8 min);
u8 b43_ppr_get_max(struct b43_wldev *dev, struct b43_ppr *ppr);
bool b43_ppr_load_max_from_sprom(struct b43_wldev *dev, struct b43_ppr *ppr,
enum b43_band band);
#endif /* LINUX_B43_PPR_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,259 @@
#ifndef B43_RADIO_2055_H_
#define B43_RADIO_2055_H_
#include <linux/types.h>
#include "tables_nphy.h"
#define B2055_GEN_SPARE 0x00 /* GEN spare */
#define B2055_SP_PINPD 0x02 /* SP PIN PD */
#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
#define B2055_MASTER1 0x11 /* Master control 1 */
#define B2055_MASTER2 0x12 /* Master control 2 */
#define B2055_PD_LGEN 0x13 /* PD LGEN */
#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
#define B2055_CAL_MISC 0x24 /* CAL MISC */
#define B2055_CAL_COUT 0x25 /* CAL Counter out */
#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
#define B2055_CAL_TS 0x2A /* CAL TS */
#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
#define B2055_PADDRV 0x2D /* PAD driver */
#define B2055_XOCTL1 0x2E /* XO Control 1 */
#define B2055_XOCTL2 0x2F /* XO Control 2 */
#define B2055_XOREGUL 0x30 /* XO Regulator */
#define B2055_XOMISC 0x31 /* XO misc */
#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
#define B2055_PLL_REF 0x35 /* PLL reference */
#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
#define B2055_VCO_REG 0x53 /* VCO Regulator */
#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
#define B2055_LGEN_DIV 0x5D /* LGEN div */
#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
struct b43_nphy_channeltab_entry_rev2 {
/* The channel number */
u8 channel;
/* The channel frequency in MHz */
u16 freq;
/* An unknown value */
u16 unk2;
/* Radio register values on channelswitch */
u8 radio_pll_ref;
u8 radio_rf_pllmod0;
u8 radio_rf_pllmod1;
u8 radio_vco_captail;
u8 radio_vco_cal1;
u8 radio_vco_cal2;
u8 radio_pll_lfc1;
u8 radio_pll_lfr1;
u8 radio_pll_lfc2;
u8 radio_lgbuf_cenbuf;
u8 radio_lgen_tune1;
u8 radio_lgen_tune2;
u8 radio_c1_lgbuf_atune;
u8 radio_c1_lgbuf_gtune;
u8 radio_c1_rx_rfr1;
u8 radio_c1_tx_pgapadtn;
u8 radio_c1_tx_mxbgtrim;
u8 radio_c2_lgbuf_atune;
u8 radio_c2_lgbuf_gtune;
u8 radio_c2_rx_rfr1;
u8 radio_c2_tx_pgapadtn;
u8 radio_c2_tx_mxbgtrim;
/* PHY register values on channelswitch */
struct b43_phy_n_sfo_cfg phy_regs;
};
/* Upload the default register value table.
* If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
* table is uploaded. If "ignore_uploadflag" is true, we upload any value
* and ignore the "UPLOAD" flag. */
void b2055_upload_inittab(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
/* Get the NPHY Channel Switch Table entry for a channel.
* Returns NULL on failure to find an entry. */
const struct b43_nphy_channeltab_entry_rev2 *
b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
#endif /* B43_RADIO_2055_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,637 @@
/*
Broadcom B43 wireless driver
IEEE 802.11n 2057 radio device data tables
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
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 "radio_2057.h"
#include "phy_common.h"
static u16 r2057_rev4_init[][2] = {
{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
{ 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c },
{ 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 },
{ 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c },
{ 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
{ 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
};
static u16 r2057_rev5_init[][2] = {
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
{ 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
{ 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 },
{ 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 },
{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
};
static u16 r2057_rev5a_init[][2] = {
{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
{ 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 },
{ 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 },
{ 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 },
{ 0x1C2, 0x80 },
};
static u16 r2057_rev7_init[][2] = {
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
{ 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 },
{ 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f },
{ 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee },
{ 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 },
{ 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 },
{ 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
};
/* TODO: Which devices should use it?
static u16 r2057_rev8_init[][2] = {
{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
};
*/
/* Extracted from MMIO dump of 6.30.223.141 */
static u16 r2057_rev9_init[][2] = {
{ 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
{ 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
{ 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
{ 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
{ 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
{ 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
{ 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
{ 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
};
/* Extracted from MMIO dump of 6.30.223.248 */
static u16 r2057_rev14_init[][2] = {
{ 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
{ 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
{ 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
{ 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
{ 0x1d4, 0x0f },
};
#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
r20, r21, r22, r23, r24, r25, r26, r27) \
.radio_vcocal_countval0 = r00, \
.radio_vcocal_countval1 = r01, \
.radio_rfpll_refmaster_sparextalsize = r02, \
.radio_rfpll_loopfilter_r1 = r03, \
.radio_rfpll_loopfilter_c2 = r04, \
.radio_rfpll_loopfilter_c1 = r05, \
.radio_cp_kpd_idac = r06, \
.radio_rfpll_mmd0 = r07, \
.radio_rfpll_mmd1 = r08, \
.radio_vcobuf_tune = r09, \
.radio_logen_mx2g_tune = r10, \
.radio_logen_mx5g_tune = r11, \
.radio_logen_indbuf2g_tune = r12, \
.radio_logen_indbuf5g_tune = r13, \
.radio_txmix2g_tune_boost_pu_core0 = r14, \
.radio_pad2g_tune_pus_core0 = r15, \
.radio_pga_boost_tune_core0 = r16, \
.radio_txmix5g_boost_tune_core0 = r17, \
.radio_pad5g_tune_misc_pus_core0 = r18, \
.radio_lna2g_tune_core0 = r19, \
.radio_lna5g_tune_core0 = r20, \
.radio_txmix2g_tune_boost_pu_core1 = r21, \
.radio_pad2g_tune_pus_core1 = r22, \
.radio_pga_boost_tune_core1 = r23, \
.radio_txmix5g_boost_tune_core1 = r24, \
.radio_pad5g_tune_misc_pus_core1 = r25, \
.radio_lna2g_tune_core1 = r26, \
.radio_lna5g_tune_core1 = r27
#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17) \
.radio_vcocal_countval0 = r00, \
.radio_vcocal_countval1 = r01, \
.radio_rfpll_refmaster_sparextalsize = r02, \
.radio_rfpll_loopfilter_r1 = r03, \
.radio_rfpll_loopfilter_c2 = r04, \
.radio_rfpll_loopfilter_c1 = r05, \
.radio_cp_kpd_idac = r06, \
.radio_rfpll_mmd0 = r07, \
.radio_rfpll_mmd1 = r08, \
.radio_vcobuf_tune = r09, \
.radio_logen_mx2g_tune = r10, \
.radio_logen_indbuf2g_tune = r11, \
.radio_txmix2g_tune_boost_pu_core0 = r12, \
.radio_pad2g_tune_pus_core0 = r13, \
.radio_lna2g_tune_core0 = r14, \
.radio_txmix2g_tune_boost_pu_core1 = r15, \
.radio_pad2g_tune_pus_core1 = r16, \
.radio_lna2g_tune_core1 = r17
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.phy_bw1a = r0, \
.phy_regs.phy_bw2 = r1, \
.phy_regs.phy_bw3 = r2, \
.phy_regs.phy_bw4 = r3, \
.phy_regs.phy_bw5 = r4, \
.phy_regs.phy_bw6 = r5
/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
{
.freq = 2412,
RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
0x03, 0xff),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
0x03, 0xff),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
0x03, 0xef),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
0x03, 0xdf),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
0x03, 0xcf),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
0x03, 0xbf),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
0x03, 0xaf),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
0x03, 0x9f),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
0x03, 0x8f),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
0x03, 0x7f),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
0x03, 0x6f),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{
.freq = 2467,
RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
0x03, 0x5f),
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
},
{
.freq = 2472,
RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
0x03, 0x4f),
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
},
{
.freq = 2484,
RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
0x03, 0x3f),
PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
}
};
/* Extracted from MMIO dump of 6.30.223.248 */
static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
{
.freq = 2412,
RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
0x43, 0xff),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
};
/* Extracted from MMIO dump of 6.30.223.141 */
static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
{
.freq = 2412,
RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{
.freq = 5180,
RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
0x3a, 0x83, 0x00, 0xfc),
PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
},
{
.freq = 5200,
RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
0x4a, 0x83, 0x00, 0xf8),
PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
},
{
.freq = 5220,
RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
0x2a, 0x73, 0x00, 0xf8),
PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
},
{
.freq = 5240,
RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
0x2b, 0x73, 0x00, 0xf8),
PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
},
{
.freq = 5745,
RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
0x02, 0x03, 0x00, 0x30),
PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
},
{
.freq = 5765,
RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
0x02, 0x03, 0x00, 0x00),
PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
},
{
.freq = 5785,
RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
0x21, 0x03, 0x00, 0x00),
PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
},
{
.freq = 5805,
RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x03, 0x00, 0x00),
PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
},
{
.freq = 5825,
RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x03, 0x00, 0x00),
PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
},
};
void r2057_upload_inittabs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
u16 *table = NULL;
u16 size, i;
switch (phy->rev) {
case 7:
table = r2057_rev4_init[0];
size = ARRAY_SIZE(r2057_rev4_init);
break;
case 8:
if (phy->radio_rev == 5) {
table = r2057_rev5_init[0];
size = ARRAY_SIZE(r2057_rev5_init);
} else if (phy->radio_rev == 7) {
table = r2057_rev7_init[0];
size = ARRAY_SIZE(r2057_rev7_init);
}
break;
case 9:
if (phy->radio_rev == 5) {
table = r2057_rev5a_init[0];
size = ARRAY_SIZE(r2057_rev5a_init);
}
break;
case 16:
if (phy->radio_rev == 9) {
table = r2057_rev9_init[0];
size = ARRAY_SIZE(r2057_rev9_init);
}
break;
case 17:
if (phy->radio_rev == 14) {
table = r2057_rev14_init[0];
size = ARRAY_SIZE(r2057_rev14_init);
}
break;
}
B43_WARN_ON(!table);
if (table) {
for (i = 0; i < size; i++, table += 2)
b43_radio_write(dev, table[0], table[1]);
}
}
void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
const struct b43_nphy_chantabent_rev7 **tabent_r7,
const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g)
{
struct b43_phy *phy = &dev->phy;
const struct b43_nphy_chantabent_rev7 *e_r7 = NULL;
const struct b43_nphy_chantabent_rev7_2g *e_r7_2g = NULL;
unsigned int len, i;
*tabent_r7 = NULL;
*tabent_r7_2g = NULL;
switch (phy->rev) {
case 8:
if (phy->radio_rev == 5) {
e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
}
break;
case 16:
if (phy->radio_rev == 9) {
e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
}
break;
case 17:
if (phy->radio_rev == 14) {
e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
}
break;
default:
break;
}
if (e_r7) {
for (i = 0; i < len; i++, e_r7++) {
if (e_r7->freq == freq) {
*tabent_r7 = e_r7;
return;
}
}
} else if (e_r7_2g) {
for (i = 0; i < len; i++, e_r7_2g++) {
if (e_r7_2g->freq == freq) {
*tabent_r7_2g = e_r7_2g;
return;
}
}
} else {
B43_WARN_ON(1);
}
}

View File

@@ -0,0 +1,506 @@
#ifndef B43_RADIO_2057_H_
#define B43_RADIO_2057_H_
#include <linux/types.h>
#include "tables_nphy.h"
#define R2057_DACBUF_VINCM_CORE0 0x000
#define R2057_IDCODE 0x001
#define R2057_RCCAL_MASTER 0x002
#define R2057_RCCAL_CAP_SIZE 0x003
#define R2057_RCAL_CONFIG 0x004
#define R2057_GPAIO_CONFIG 0x005
#define R2057_GPAIO_SEL1 0x006
#define R2057_GPAIO_SEL0 0x007
#define R2057_CLPO_CONFIG 0x008
#define R2057_BANDGAP_CONFIG 0x009
#define R2057_BANDGAP_RCAL_TRIM 0x00a
#define R2057_AFEREG_CONFIG 0x00b
#define R2057_TEMPSENSE_CONFIG 0x00c
#define R2057_XTAL_CONFIG1 0x00d
#define R2057_XTAL_ICORE_SIZE 0x00e
#define R2057_XTAL_BUF_SIZE 0x00f
#define R2057_XTAL_PULLCAP_SIZE 0x010
#define R2057_RFPLL_MASTER 0x011
#define R2057_VCOMONITOR_VTH_L 0x012
#define R2057_VCOMONITOR_VTH_H 0x013
#define R2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x014
#define R2057_VCO_VARCSIZE_IDAC 0x015
#define R2057_VCOCAL_COUNTVAL0 0x016
#define R2057_VCOCAL_COUNTVAL1 0x017
#define R2057_VCOCAL_INTCLK_COUNT 0x018
#define R2057_VCOCAL_MASTER 0x019
#define R2057_VCOCAL_NUMCAPCHANGE 0x01a
#define R2057_VCOCAL_WINSIZE 0x01b
#define R2057_VCOCAL_DELAY_AFTER_REFRESH 0x01c
#define R2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x01d
#define R2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x01e
#define R2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x01f
#define R2057_VCO_FORCECAPEN_FORCECAP1 0x020
#define R2057_VCO_FORCECAP0 0x021
#define R2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x022
#define R2057_RFPLL_PFD_RESET_PW 0x023
#define R2057_RFPLL_LOOPFILTER_R2 0x024
#define R2057_RFPLL_LOOPFILTER_R1 0x025
#define R2057_RFPLL_LOOPFILTER_C3 0x026
#define R2057_RFPLL_LOOPFILTER_C2 0x027
#define R2057_RFPLL_LOOPFILTER_C1 0x028
#define R2057_CP_KPD_IDAC 0x029
#define R2057_RFPLL_IDACS 0x02a
#define R2057_RFPLL_MISC_EN 0x02b
#define R2057_RFPLL_MMD0 0x02c
#define R2057_RFPLL_MMD1 0x02d
#define R2057_RFPLL_MISC_CAL_RESETN 0x02e
#define R2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x02f
#define R2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x030
#define R2057_VCOCAL_READCAP0 0x031
#define R2057_VCOCAL_READCAP1 0x032
#define R2057_VCOCAL_STATUS 0x033
#define R2057_LOGEN_PUS 0x034
#define R2057_LOGEN_PTAT_RESETS 0x035
#define R2057_VCOBUF_IDACS 0x036
#define R2057_VCOBUF_TUNE 0x037
#define R2057_CMOSBUF_TX2GQ_IDACS 0x038
#define R2057_CMOSBUF_TX2GI_IDACS 0x039
#define R2057_CMOSBUF_TX5GQ_IDACS 0x03a
#define R2057_CMOSBUF_TX5GI_IDACS 0x03b
#define R2057_CMOSBUF_RX2GQ_IDACS 0x03c
#define R2057_CMOSBUF_RX2GI_IDACS 0x03d
#define R2057_CMOSBUF_RX5GQ_IDACS 0x03e
#define R2057_CMOSBUF_RX5GI_IDACS 0x03f
#define R2057_LOGEN_MX2G_IDACS 0x040
#define R2057_LOGEN_MX2G_TUNE 0x041
#define R2057_LOGEN_MX5G_IDACS 0x042
#define R2057_LOGEN_MX5G_TUNE 0x043
#define R2057_LOGEN_MX5G_RCCR 0x044
#define R2057_LOGEN_INDBUF2G_IDAC 0x045
#define R2057_LOGEN_INDBUF2G_IBOOST 0x046
#define R2057_LOGEN_INDBUF2G_TUNE 0x047
#define R2057_LOGEN_INDBUF5G_IDAC 0x048
#define R2057_LOGEN_INDBUF5G_IBOOST 0x049
#define R2057_LOGEN_INDBUF5G_TUNE 0x04a
#define R2057_CMOSBUF_TX_RCCR 0x04b
#define R2057_CMOSBUF_RX_RCCR 0x04c
#define R2057_LOGEN_SEL_PKDET 0x04d
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
/* MISC core 0 */
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
#define R2057_TXGM_TXRF_PUS_CORE0 0x050
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
#define R2057_TXGM_GAIN_CORE0 0x056
#define R2057_TXGM2G_PKDET_PUS_CORE0 0x057
#define R2057_PAD2G_PTATS_CORE0 0x058
#define R2057_PAD2G_IDACS_CORE0 0x059
#define R2057_PAD2G_BOOST_PU_CORE0 0x05a
#define R2057_PAD2G_CASCV_GAIN_CORE0 0x05b
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x05c
#define R2057_TXMIX2G_LODC_CORE0 0x05d
#define R2057_PAD2G_TUNE_PUS_CORE0 0x05e
#define R2057_IPA2G_GAIN_CORE0 0x05f
#define R2057_TSSI2G_SPARE1_CORE0 0x060
#define R2057_TSSI2G_SPARE2_CORE0 0x061
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x062
#define R2057_IPA2G_IMAIN_CORE0 0x063
#define R2057_IPA2G_CASCONV_CORE0 0x064
#define R2057_IPA2G_CASCOFFV_CORE0 0x065
#define R2057_IPA2G_BIAS_FILTER_CORE0 0x066
#define R2057_TX5G_PKDET_CORE0 0x069
#define R2057_PGA_PTAT_TXGM5G_PU_CORE0 0x06a
#define R2057_PAD5G_PTATS1_CORE0 0x06b
#define R2057_PAD5G_CLASS_PTATS2_CORE0 0x06c
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x06d
#define R2057_PAD5G_CASCV_IMAIN_CORE0 0x06e
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x06f
#define R2057_PGA_BOOST_TUNE_CORE0 0x070
#define R2057_PGA_GAIN_CORE0 0x071
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x072
#define R2057_TXMIX5G_BOOST_TUNE_CORE0 0x073
#define R2057_PAD5G_TUNE_MISC_PUS_CORE0 0x074
#define R2057_IPA5G_IAUX_CORE0 0x075
#define R2057_IPA5G_GAIN_CORE0 0x076
#define R2057_TSSI5G_SPARE1_CORE0 0x077
#define R2057_TSSI5G_SPARE2_CORE0 0x078
#define R2057_IPA5G_CASCOFFV_PU_CORE0 0x079
#define R2057_IPA5G_PTAT_CORE0 0x07a
#define R2057_IPA5G_IMAIN_CORE0 0x07b
#define R2057_IPA5G_CASCONV_CORE0 0x07c
#define R2057_IPA5G_BIAS_FILTER_CORE0 0x07d
#define R2057_PAD_BIAS_FILTER_BWS_CORE0 0x080
#define R2057_TR2G_CONFIG1_CORE0_NU 0x081
#define R2057_TR2G_CONFIG2_CORE0_NU 0x082
#define R2057_LNA5G_RFEN_CORE0 0x083
#define R2057_TR5G_CONFIG2_CORE0_NU 0x084
#define R2057_RXRFBIAS_IBOOST_PU_CORE0 0x085
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x086
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x087
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x088
#define R2057_RXMIX_CMFBITAIL_PU_CORE0 0x089
#define R2057_LNA2_IMAIN_PTAT_PU_CORE0 0x08a
#define R2057_LNA2_IAUX_PTAT_CORE0 0x08b
#define R2057_LNA1_IMAIN_PTAT_PU_CORE0 0x08c
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x08d
#define R2057_RXRFBIAS_BANDSEL_CORE0 0x08e
#define R2057_TIA_CONFIG_CORE0 0x08f
#define R2057_TIA_IQGAIN_CORE0 0x090
#define R2057_TIA_IBIAS2_CORE0 0x091
#define R2057_TIA_IBIAS1_CORE0 0x092
#define R2057_TIA_SPARE_Q_CORE0 0x093
#define R2057_TIA_SPARE_I_CORE0 0x094
#define R2057_RXMIX2G_PUS_CORE0 0x095
#define R2057_RXMIX2G_VCMREFS_CORE0 0x096
#define R2057_RXMIX2G_LODC_QI_CORE0 0x097
#define R2057_W12G_BW_LNA2G_PUS_CORE0 0x098
#define R2057_LNA2G_GAIN_CORE0 0x099
#define R2057_LNA2G_TUNE_CORE0 0x09a
#define R2057_RXMIX5G_PUS_CORE0 0x09b
#define R2057_RXMIX5G_VCMREFS_CORE0 0x09c
#define R2057_RXMIX5G_LODC_QI_CORE0 0x09d
#define R2057_W15G_BW_LNA5G_PUS_CORE0 0x09e
#define R2057_LNA5G_GAIN_CORE0 0x09f
#define R2057_LNA5G_TUNE_CORE0 0x0a0
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0x0a1
#define R2057_RXBB_BIAS_MASTER_CORE0 0x0a2
#define R2057_RXBB_VGABUF_IDACS_CORE0 0x0a3
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0x0a4
#define R2057_TXBUF_VINCM_CORE0 0x0a5
#define R2057_TXBUF_IDACS_CORE0 0x0a6
#define R2057_LPF_RESP_RXBUF_BW_CORE0 0x0a7
#define R2057_RXBB_CC_CORE0 0x0a8
#define R2057_RXBB_SPARE3_CORE0 0x0a9
#define R2057_RXBB_RCCAL_HPC_CORE0 0x0aa
#define R2057_LPF_IDACS_CORE0 0x0ab
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0x0ac
#define R2057_TXBUF_GAIN_CORE0 0x0ad
#define R2057_AFELOOPBACK_AACI_RESP_CORE0 0x0ae
#define R2057_RXBUF_DEGEN_CORE0 0x0af
#define R2057_RXBB_SPARE2_CORE0 0x0b0
#define R2057_RXBB_SPARE1_CORE0 0x0b1
#define R2057_RSSI_MASTER_CORE0 0x0b2
#define R2057_W2_MASTER_CORE0 0x0b3
#define R2057_NB_MASTER_CORE0 0x0b4
#define R2057_W2_IDACS0_Q_CORE0 0x0b5
#define R2057_W2_IDACS1_Q_CORE0 0x0b6
#define R2057_W2_IDACS0_I_CORE0 0x0b7
#define R2057_W2_IDACS1_I_CORE0 0x0b8
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0x0b9
#define R2057_NB_IDACS_Q_CORE0 0x0ba
#define R2057_NB_IDACS_I_CORE0 0x0bb
#define R2057_BACKUP4_CORE0 0x0c1
#define R2057_BACKUP3_CORE0 0x0c2
#define R2057_BACKUP2_CORE0 0x0c3
#define R2057_BACKUP1_CORE0 0x0c4
#define R2057_SPARE16_CORE0 0x0c5
#define R2057_SPARE15_CORE0 0x0c6
#define R2057_SPARE14_CORE0 0x0c7
#define R2057_SPARE13_CORE0 0x0c8
#define R2057_SPARE12_CORE0 0x0c9
#define R2057_SPARE11_CORE0 0x0ca
#define R2057_TX2G_BIAS_RESETS_CORE0 0x0cb
#define R2057_TX5G_BIAS_RESETS_CORE0 0x0cc
#define R2057_IQTEST_SEL_PU 0x0cd
#define R2057_XTAL_CONFIG2 0x0ce
#define R2057_BUFS_MISC_LPFBW_CORE0 0x0cf
#define R2057_TXLPF_RCCAL_CORE0 0x0d0
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
#define R2057_LPF_GAIN_CORE0 0x0d2
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
/* MISC core 1 */
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
#define R2057_TXGM_GAIN_CORE1 0x0db
#define R2057_TXGM2G_PKDET_PUS_CORE1 0x0dc
#define R2057_PAD2G_PTATS_CORE1 0x0dd
#define R2057_PAD2G_IDACS_CORE1 0x0de
#define R2057_PAD2G_BOOST_PU_CORE1 0x0df
#define R2057_PAD2G_CASCV_GAIN_CORE1 0x0e0
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0x0e1
#define R2057_TXMIX2G_LODC_CORE1 0x0e2
#define R2057_PAD2G_TUNE_PUS_CORE1 0x0e3
#define R2057_IPA2G_GAIN_CORE1 0x0e4
#define R2057_TSSI2G_SPARE1_CORE1 0x0e5
#define R2057_TSSI2G_SPARE2_CORE1 0x0e6
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0x0e7
#define R2057_IPA2G_IMAIN_CORE1 0x0e8
#define R2057_IPA2G_CASCONV_CORE1 0x0e9
#define R2057_IPA2G_CASCOFFV_CORE1 0x0ea
#define R2057_IPA2G_BIAS_FILTER_CORE1 0x0eb
#define R2057_TX5G_PKDET_CORE1 0x0ee
#define R2057_PGA_PTAT_TXGM5G_PU_CORE1 0x0ef
#define R2057_PAD5G_PTATS1_CORE1 0x0f0
#define R2057_PAD5G_CLASS_PTATS2_CORE1 0x0f1
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE1 0x0f2
#define R2057_PAD5G_CASCV_IMAIN_CORE1 0x0f3
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0x0f4
#define R2057_PGA_BOOST_TUNE_CORE1 0x0f5
#define R2057_PGA_GAIN_CORE1 0x0f6
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0x0f7
#define R2057_TXMIX5G_BOOST_TUNE_CORE1 0x0f8
#define R2057_PAD5G_TUNE_MISC_PUS_CORE1 0x0f9
#define R2057_IPA5G_IAUX_CORE1 0x0fa
#define R2057_IPA5G_GAIN_CORE1 0x0fb
#define R2057_TSSI5G_SPARE1_CORE1 0x0fc
#define R2057_TSSI5G_SPARE2_CORE1 0x0fd
#define R2057_IPA5G_CASCOFFV_PU_CORE1 0x0fe
#define R2057_IPA5G_PTAT_CORE1 0x0ff
#define R2057_IPA5G_IMAIN_CORE1 0x100
#define R2057_IPA5G_CASCONV_CORE1 0x101
#define R2057_IPA5G_BIAS_FILTER_CORE1 0x102
#define R2057_PAD_BIAS_FILTER_BWS_CORE1 0x105
#define R2057_TR2G_CONFIG1_CORE1_NU 0x106
#define R2057_TR2G_CONFIG2_CORE1_NU 0x107
#define R2057_LNA5G_RFEN_CORE1 0x108
#define R2057_TR5G_CONFIG2_CORE1_NU 0x109
#define R2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d
#define R2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e
#define R2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f
#define R2057_LNA2_IAUX_PTAT_CORE1 0x110
#define R2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
#define R2057_RXRFBIAS_BANDSEL_CORE1 0x113
#define R2057_TIA_CONFIG_CORE1 0x114
#define R2057_TIA_IQGAIN_CORE1 0x115
#define R2057_TIA_IBIAS2_CORE1 0x116
#define R2057_TIA_IBIAS1_CORE1 0x117
#define R2057_TIA_SPARE_Q_CORE1 0x118
#define R2057_TIA_SPARE_I_CORE1 0x119
#define R2057_RXMIX2G_PUS_CORE1 0x11a
#define R2057_RXMIX2G_VCMREFS_CORE1 0x11b
#define R2057_RXMIX2G_LODC_QI_CORE1 0x11c
#define R2057_W12G_BW_LNA2G_PUS_CORE1 0x11d
#define R2057_LNA2G_GAIN_CORE1 0x11e
#define R2057_LNA2G_TUNE_CORE1 0x11f
#define R2057_RXMIX5G_PUS_CORE1 0x120
#define R2057_RXMIX5G_VCMREFS_CORE1 0x121
#define R2057_RXMIX5G_LODC_QI_CORE1 0x122
#define R2057_W15G_BW_LNA5G_PUS_CORE1 0x123
#define R2057_LNA5G_GAIN_CORE1 0x124
#define R2057_LNA5G_TUNE_CORE1 0x125
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126
#define R2057_RXBB_BIAS_MASTER_CORE1 0x127
#define R2057_RXBB_VGABUF_IDACS_CORE1 0x128
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
#define R2057_TXBUF_VINCM_CORE1 0x12a
#define R2057_TXBUF_IDACS_CORE1 0x12b
#define R2057_LPF_RESP_RXBUF_BW_CORE1 0x12c
#define R2057_RXBB_CC_CORE1 0x12d
#define R2057_RXBB_SPARE3_CORE1 0x12e
#define R2057_RXBB_RCCAL_HPC_CORE1 0x12f
#define R2057_LPF_IDACS_CORE1 0x130
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131
#define R2057_TXBUF_GAIN_CORE1 0x132
#define R2057_AFELOOPBACK_AACI_RESP_CORE1 0x133
#define R2057_RXBUF_DEGEN_CORE1 0x134
#define R2057_RXBB_SPARE2_CORE1 0x135
#define R2057_RXBB_SPARE1_CORE1 0x136
#define R2057_RSSI_MASTER_CORE1 0x137
#define R2057_W2_MASTER_CORE1 0x138
#define R2057_NB_MASTER_CORE1 0x139
#define R2057_W2_IDACS0_Q_CORE1 0x13a
#define R2057_W2_IDACS1_Q_CORE1 0x13b
#define R2057_W2_IDACS0_I_CORE1 0x13c
#define R2057_W2_IDACS1_I_CORE1 0x13d
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e
#define R2057_NB_IDACS_Q_CORE1 0x13f
#define R2057_NB_IDACS_I_CORE1 0x140
#define R2057_BACKUP4_CORE1 0x146
#define R2057_BACKUP3_CORE1 0x147
#define R2057_BACKUP2_CORE1 0x148
#define R2057_BACKUP1_CORE1 0x149
#define R2057_SPARE16_CORE1 0x14a
#define R2057_SPARE15_CORE1 0x14b
#define R2057_SPARE14_CORE1 0x14c
#define R2057_SPARE13_CORE1 0x14d
#define R2057_SPARE12_CORE1 0x14e
#define R2057_SPARE11_CORE1 0x14f
#define R2057_TX2G_BIAS_RESETS_CORE1 0x150
#define R2057_TX5G_BIAS_RESETS_CORE1 0x151
#define R2057_SPARE8_CORE1 0x152
#define R2057_SPARE7_CORE1 0x153
#define R2057_BUFS_MISC_LPFBW_CORE1 0x154
#define R2057_TXLPF_RCCAL_CORE1 0x155
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
#define R2057_LPF_GAIN_CORE1 0x157
#define R2057_DACBUF_IDACS_BW_CORE1 0x158
#define R2057_DACBUF_VINCM_CORE1 0x159
#define R2057_RCCAL_START_R1_Q1_P1 0x15a
#define R2057_RCCAL_X1 0x15b
#define R2057_RCCAL_TRC0 0x15c
#define R2057_RCCAL_TRC1 0x15d
#define R2057_RCCAL_DONE_OSCCAP 0x15e
#define R2057_RCCAL_N0_0 0x15f
#define R2057_RCCAL_N0_1 0x160
#define R2057_RCCAL_N1_0 0x161
#define R2057_RCCAL_N1_1 0x162
#define R2057_RCAL_STATUS 0x163
#define R2057_XTALPUOVR_PINCTRL 0x164
#define R2057_OVR_REG0 0x165
#define R2057_OVR_REG1 0x166
#define R2057_OVR_REG2 0x167
#define R2057_OVR_REG3 0x168
#define R2057_OVR_REG4 0x169
#define R2057_RCCAL_SCAP_VAL 0x16a
#define R2057_RCCAL_BCAP_VAL 0x16b
#define R2057_RCCAL_HPC_VAL 0x16c
#define R2057_RCCAL_OVERRIDES 0x16d
/* TX core 0 */
#define R2057_TX0_IQCAL_GAIN_BW 0x170
#define R2057_TX0_LOFT_FINE_I 0x171
#define R2057_TX0_LOFT_FINE_Q 0x172
#define R2057_TX0_LOFT_COARSE_I 0x173
#define R2057_TX0_LOFT_COARSE_Q 0x174
#define R2057_TX0_TX_SSI_MASTER 0x175
#define R2057_TX0_IQCAL_VCM_HG 0x176
#define R2057_TX0_IQCAL_IDAC 0x177
#define R2057_TX0_TSSI_VCM 0x178
#define R2057_TX0_TX_SSI_MUX 0x179
#define R2057_TX0_TSSIA 0x17a
#define R2057_TX0_TSSIG 0x17b
#define R2057_TX0_TSSI_MISC1 0x17c
#define R2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
/* TX core 1 */
#define R2057_TX1_IQCAL_GAIN_BW 0x190
#define R2057_TX1_LOFT_FINE_I 0x191
#define R2057_TX1_LOFT_FINE_Q 0x192
#define R2057_TX1_LOFT_COARSE_I 0x193
#define R2057_TX1_LOFT_COARSE_Q 0x194
#define R2057_TX1_TX_SSI_MASTER 0x195
#define R2057_TX1_IQCAL_VCM_HG 0x196
#define R2057_TX1_IQCAL_IDAC 0x197
#define R2057_TX1_TSSI_VCM 0x198
#define R2057_TX1_TX_SSI_MUX 0x199
#define R2057_TX1_TSSIA 0x19a
#define R2057_TX1_TSSIG 0x19b
#define R2057_TX1_TSSI_MISC1 0x19c
#define R2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
#define R2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4
#define R2057_AFE_STATUS_VCM_I_CORE0 0x1a5
#define R2057_AFE_STATUS_VCM_Q_CORE0 0x1a6
#define R2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7
#define R2057_AFE_SET_VCM_I_CORE1 0x1a8
#define R2057_AFE_SET_VCM_Q_CORE1 0x1a9
#define R2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa
#define R2057_AFE_STATUS_VCM_I_CORE1 0x1ab
#define R2057_AFE_STATUS_VCM_Q_CORE1 0x1ac
#define R2057v7_DACBUF_VINCM_CORE0 0x1ad
#define R2057v7_RCCAL_MASTER 0x1ae
#define R2057v7_TR2G_CONFIG3_CORE0_NU 0x1af
#define R2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0
#define R2057v7_LOGEN_PUS1 0x1b1
#define R2057v7_OVR_REG5 0x1b2
#define R2057v7_OVR_REG6 0x1b3
#define R2057v7_OVR_REG7 0x1b4
#define R2057v7_OVR_REG8 0x1b5
#define R2057v7_OVR_REG9 0x1b6
#define R2057v7_OVR_REG10 0x1b7
#define R2057v7_OVR_REG11 0x1b8
#define R2057v7_OVR_REG12 0x1b9
#define R2057v7_OVR_REG13 0x1ba
#define R2057v7_OVR_REG14 0x1bb
#define R2057v7_OVR_REG15 0x1bc
#define R2057v7_OVR_REG16 0x1bd
#define R2057v7_OVR_REG1 0x1be
#define R2057v7_OVR_REG18 0x1bf
#define R2057v7_OVR_REG19 0x1c0
#define R2057v7_OVR_REG20 0x1c1
#define R2057v7_OVR_REG21 0x1c2
#define R2057v7_OVR_REG2 0x1c3
#define R2057v7_OVR_REG23 0x1c4
#define R2057v7_OVR_REG24 0x1c5
#define R2057v7_OVR_REG25 0x1c6
#define R2057v7_OVR_REG26 0x1c7
#define R2057v7_OVR_REG27 0x1c8
#define R2057v7_OVR_REG28 0x1c9
#define R2057v7_IQTEST_SEL_PU2 0x1ca
#define R2057_VCM_MASK 0x7
struct b43_nphy_chantabent_rev7 {
/* The channel frequency in MHz */
u16 freq;
/* Radio regs values on channelswitch */
u8 radio_vcocal_countval0;
u8 radio_vcocal_countval1;
u8 radio_rfpll_refmaster_sparextalsize;
u8 radio_rfpll_loopfilter_r1;
u8 radio_rfpll_loopfilter_c2;
u8 radio_rfpll_loopfilter_c1;
u8 radio_cp_kpd_idac;
u8 radio_rfpll_mmd0;
u8 radio_rfpll_mmd1;
u8 radio_vcobuf_tune;
u8 radio_logen_mx2g_tune;
u8 radio_logen_mx5g_tune;
u8 radio_logen_indbuf2g_tune;
u8 radio_logen_indbuf5g_tune;
u8 radio_txmix2g_tune_boost_pu_core0;
u8 radio_pad2g_tune_pus_core0;
u8 radio_pga_boost_tune_core0;
u8 radio_txmix5g_boost_tune_core0;
u8 radio_pad5g_tune_misc_pus_core0;
u8 radio_lna2g_tune_core0;
u8 radio_lna5g_tune_core0;
u8 radio_txmix2g_tune_boost_pu_core1;
u8 radio_pad2g_tune_pus_core1;
u8 radio_pga_boost_tune_core1;
u8 radio_txmix5g_boost_tune_core1;
u8 radio_pad5g_tune_misc_pus_core1;
u8 radio_lna2g_tune_core1;
u8 radio_lna5g_tune_core1;
/* PHY res values on channelswitch */
struct b43_phy_n_sfo_cfg phy_regs;
};
struct b43_nphy_chantabent_rev7_2g {
/* The channel frequency in MHz */
u16 freq;
/* Radio regs values on channelswitch */
u8 radio_vcocal_countval0;
u8 radio_vcocal_countval1;
u8 radio_rfpll_refmaster_sparextalsize;
u8 radio_rfpll_loopfilter_r1;
u8 radio_rfpll_loopfilter_c2;
u8 radio_rfpll_loopfilter_c1;
u8 radio_cp_kpd_idac;
u8 radio_rfpll_mmd0;
u8 radio_rfpll_mmd1;
u8 radio_vcobuf_tune;
u8 radio_logen_mx2g_tune;
u8 radio_logen_indbuf2g_tune;
u8 radio_txmix2g_tune_boost_pu_core0;
u8 radio_pad2g_tune_pus_core0;
u8 radio_lna2g_tune_core0;
u8 radio_txmix2g_tune_boost_pu_core1;
u8 radio_pad2g_tune_pus_core1;
u8 radio_lna2g_tune_core1;
/* PHY regs values on channelswitch */
struct b43_phy_n_sfo_cfg phy_regs;
};
void r2057_upload_inittabs(struct b43_wldev *dev);
void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
const struct b43_nphy_chantabent_rev7 **tabent_r7,
const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g);
#endif /* B43_RADIO_2057_H_ */

View File

@@ -0,0 +1,364 @@
/*
Broadcom B43 wireless driver
IEEE 802.11n 2059 radio device data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
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 "radio_2059.h"
/* Extracted from MMIO dump of 6.30.223.141 */
static u16 r2059_phy_rev1_init[][2] = {
{ 0x051, 0x70 }, { 0x05a, 0x03 }, { 0x079, 0x01 }, { 0x082, 0x70 },
{ 0x083, 0x00 }, { 0x084, 0x70 }, { 0x09a, 0x7f }, { 0x0b6, 0x10 },
{ 0x188, 0x05 },
};
#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
r20) \
.radio_syn16 = r00, \
.radio_syn17 = r01, \
.radio_syn22 = r02, \
.radio_syn25 = r03, \
.radio_syn27 = r04, \
.radio_syn28 = r05, \
.radio_syn29 = r06, \
.radio_syn2c = r07, \
.radio_syn2d = r08, \
.radio_syn37 = r09, \
.radio_syn41 = r10, \
.radio_syn43 = r11, \
.radio_syn47 = r12, \
.radio_rxtx4a = r13, \
.radio_rxtx58 = r14, \
.radio_rxtx5a = r15, \
.radio_rxtx6a = r16, \
.radio_rxtx6d = r17, \
.radio_rxtx6e = r18, \
.radio_rxtx92 = r19, \
.radio_rxtx98 = r20
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.bw1 = r0, \
.phy_regs.bw2 = r1, \
.phy_regs.bw3 = r2, \
.phy_regs.bw4 = r3, \
.phy_regs.bw5 = r4, \
.phy_regs.bw6 = r5
/* Extracted from MMIO dump of 6.30.223.141
* TODO: Values for channels 12 & 13 are outdated (from some old 5.x driver)!
*/
static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
{
.freq = 2412,
RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xd0, 0x00),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xd0, 0x00),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xd0, 0x00),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xa0, 0x00),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xa0, 0x00),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0xa0, 0x00),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0x80, 0x00),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0x80, 0x00),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0x80, 0x00),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0x60, 0x00),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x73,
0x00, 0x00, 0x00, 0x60, 0x00),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{ .freq = 2467,
RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
},
{ .freq = 2472,
RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
},
{
.freq = 5180,
RADIOREGS(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
0x0f, 0x4f, 0xa3, 0x00, 0xfc),
PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
},
{
.freq = 5200,
RADIOREGS(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
0x0f, 0x4f, 0x93, 0x00, 0xfb),
PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
},
{
.freq = 5220,
RADIOREGS(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
0x0f, 0x4f, 0x93, 0x00, 0xea),
PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
},
{
.freq = 5240,
RADIOREGS(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
0x0f, 0x4f, 0x93, 0x00, 0xda),
PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
},
{
.freq = 5260,
RADIOREGS(0xd9, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0e,
0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
0x0f, 0x4f, 0x93, 0x00, 0xca),
PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
},
{
.freq = 5280,
RADIOREGS(0xe0, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x10,
0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
0x0f, 0x4f, 0x93, 0x00, 0xb9),
PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
},
{
.freq = 5300,
RADIOREGS(0xe6, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x12,
0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
0x0f, 0x4c, 0x83, 0x00, 0xb8),
PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
},
{
.freq = 5320,
RADIOREGS(0xed, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x14,
0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
0x0f, 0x4c, 0x83, 0x00, 0xa8),
PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
},
{
.freq = 5500,
RADIOREGS(0x29, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x26,
0x02, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00,
0x0a, 0x46, 0x43, 0x00, 0x75),
PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
},
{
.freq = 5520,
RADIOREGS(0x30, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x28,
0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
0x0a, 0x46, 0x43, 0x00, 0x75),
PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
},
{
.freq = 5540,
RADIOREGS(0x36, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2a,
0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
0x0a, 0x46, 0x43, 0x00, 0x75),
PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
},
{
.freq = 5560,
RADIOREGS(0x3d, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2c,
0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
0x0a, 0x46, 0x43, 0x00, 0x75),
PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
},
{
.freq = 5580,
RADIOREGS(0x44, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2e,
0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
0x0a, 0x46, 0x43, 0x00, 0x74),
PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
},
{
.freq = 5600,
RADIOREGS(0x4a, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x30,
0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
0x09, 0x44, 0x23, 0x00, 0x54),
PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
},
{
.freq = 5620,
RADIOREGS(0x51, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x32,
0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x09, 0x44, 0x23, 0x00, 0x54),
PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
},
{
.freq = 5640,
RADIOREGS(0x58, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x34,
0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x09, 0x44, 0x23, 0x00, 0x43),
PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
},
{
.freq = 5660,
RADIOREGS(0x5e, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x36,
0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x09, 0x43, 0x23, 0x00, 0x43),
PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
},
{
.freq = 5680,
RADIOREGS(0x65, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x38,
0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x09, 0x42, 0x23, 0x00, 0x43),
PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
},
{
.freq = 5700,
RADIOREGS(0x6c, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x3a,
0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x08, 0x42, 0x13, 0x00, 0x32),
PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
},
{
.freq = 5745,
RADIOREGS(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
0x04, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
0x08, 0x42, 0x13, 0x00, 0x21),
PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
},
{
.freq = 5765,
RADIOREGS(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
0x04, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
0x08, 0x42, 0x13, 0x00, 0x11),
PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
},
{
.freq = 5785,
RADIOREGS(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
0x08, 0x42, 0x13, 0x00, 0x00),
PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
},
{
.freq = 5805,
RADIOREGS(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
0x06, 0x41, 0x03, 0x00, 0x00),
PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
},
{
.freq = 5825,
RADIOREGS(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
0x06, 0x41, 0x03, 0x00, 0x00),
PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
},
};
void r2059_upload_inittabs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
u16 *table = NULL;
u16 size, i;
switch (phy->rev) {
case 1:
table = r2059_phy_rev1_init[0];
size = ARRAY_SIZE(r2059_phy_rev1_init);
break;
default:
B43_WARN_ON(1);
return;
}
for (i = 0; i < size; i++, table += 2)
b43_radio_write(dev, R2059_ALL | table[0], table[1]);
}
const struct b43_phy_ht_channeltab_e_radio2059
*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
{
const struct b43_phy_ht_channeltab_e_radio2059 *e;
unsigned int i;
e = b43_phy_ht_channeltab_radio2059;
for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) {
if (e->freq == freq)
return e;
}
return NULL;
}

View File

@@ -0,0 +1,60 @@
#ifndef B43_RADIO_2059_H_
#define B43_RADIO_2059_H_
#include <linux/types.h>
#include "phy_ht.h"
#define R2059_C1 0x000
#define R2059_C2 0x400
#define R2059_C3 0x800
#define R2059_ALL 0xC00
#define R2059_RCAL_CONFIG 0x004
#define R2059_RFPLL_MASTER 0x011
#define R2059_RFPLL_MISC_EN 0x02b
#define R2059_RFPLL_MISC_CAL_RESETN 0x02e
#define R2059_XTAL_CONFIG2 0x0c0
#define R2059_RCCAL_START_R1_Q1_P1 0x13c
#define R2059_RCCAL_X1 0x13d
#define R2059_RCCAL_TRC0 0x13e
#define R2059_RCCAL_DONE_OSCCAP 0x140
#define R2059_RCAL_STATUS 0x145
#define R2059_RCCAL_MASTER 0x17f
/* Values for various registers uploaded on channel switching */
struct b43_phy_ht_channeltab_e_radio2059 {
/* The channel frequency in MHz */
u16 freq;
/* Values for radio registers */
u8 radio_syn16;
u8 radio_syn17;
u8 radio_syn22;
u8 radio_syn25;
u8 radio_syn27;
u8 radio_syn28;
u8 radio_syn29;
u8 radio_syn2c;
u8 radio_syn2d;
u8 radio_syn37;
u8 radio_syn41;
u8 radio_syn43;
u8 radio_syn47;
u8 radio_rxtx4a;
u8 radio_rxtx58;
u8 radio_rxtx5a;
u8 radio_rxtx6a;
u8 radio_rxtx6d;
u8 radio_rxtx6e;
u8 radio_rxtx92;
u8 radio_rxtx98;
/* Values for PHY registers */
struct b43_phy_ht_channeltab_e_phy phy_regs;
};
void r2059_upload_inittabs(struct b43_wldev *dev);
const struct b43_phy_ht_channeltab_e_radio2059
*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
#endif /* B43_RADIO_2059_H_ */

View File

@@ -0,0 +1,70 @@
/*
Broadcom B43 wireless driver
RFKILL support
Copyright (c) 2007 Michael Buesch <m@bues.ch>
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"
/* Returns TRUE, if the radio is enabled in hardware. */
bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
{
return !(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
& B43_MMIO_RADIO_HWENABLED_HI_MASK);
}
/* The poll callback for the hardware button. */
void b43_rfkill_poll(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
bool enabled;
bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
if (b43_bus_powerup(dev, 0)) {
mutex_unlock(&wl->mutex);
return;
}
b43_device_enable(dev, 0);
brought_up = true;
}
enabled = b43_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
if (enabled != dev->phy.radio_on)
b43_software_rfkill(dev, !enabled);
}
if (brought_up) {
b43_device_disable(dev, 0);
b43_bus_may_powerdown(dev);
}
mutex_unlock(&wl->mutex);
}

View File

@@ -0,0 +1,11 @@
#ifndef B43_RFKILL_H_
#define B43_RFKILL_H_
struct ieee80211_hw;
struct b43_wldev;
void b43_rfkill_poll(struct ieee80211_hw *hw);
bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
#endif /* B43_RFKILL_H_ */

View File

@@ -0,0 +1,207 @@
/*
* Broadcom B43 wireless driver
*
* SDIO over Sonics Silicon Backplane bus glue for b43.
*
* Copyright (C) 2009 Albert Herranz
* Copyright (C) 2009 Michael Buesch <m@bues.ch>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/slab.h>
#include <linux/ssb/ssb.h>
#include "sdio.h"
#include "b43.h"
#define HNBU_CHIPID 0x01 /* vendor & device id */
#define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */
static const struct b43_sdio_quirk {
u16 vendor;
u16 device;
unsigned int quirks;
} b43_sdio_quirks[] = {
{ 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
{ },
};
static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
{
const struct b43_sdio_quirk *q;
for (q = b43_sdio_quirks; q->quirks; q++) {
if (vendor == q->vendor && device == q->device)
return q->quirks;
}
return 0;
}
static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
struct b43_wldev *dev = sdio->irq_handler_opaque;
if (unlikely(b43_status(dev) < B43_STAT_STARTED))
return;
sdio_release_host(func);
sdio->irq_handler(dev);
sdio_claim_host(func);
}
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
int err;
sdio->irq_handler_opaque = dev;
sdio->irq_handler = handler;
sdio_claim_host(func);
err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
sdio_release_host(func);
return err;
}
void b43_sdio_free_irq(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
sdio_claim_host(func);
sdio_release_irq(func);
sdio_release_host(func);
sdio->irq_handler_opaque = NULL;
sdio->irq_handler = NULL;
}
static int b43_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
u16 vendor = 0, device = 0;
int error;
/* Look for the card chip identifier. */
tuple = func->tuples;
while (tuple) {
switch (tuple->code) {
case 0x80:
switch (tuple->data[0]) {
case HNBU_CHIPID:
if (tuple->size != 5)
break;
vendor = tuple->data[1] | (tuple->data[2]<<8);
device = tuple->data[3] | (tuple->data[4]<<8);
dev_info(&func->dev, "Chip ID %04x:%04x\n",
vendor, device);
break;
default:
break;
}
break;
default:
break;
}
tuple = tuple->next;
}
if (!vendor || !device) {
error = -ENODEV;
goto out;
}
sdio_claim_host(func);
error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
if (error) {
dev_err(&func->dev, "failed to set block size to %u bytes,"
" error %d\n", B43_SDIO_BLOCK_SIZE, error);
goto err_release_host;
}
error = sdio_enable_func(func);
if (error) {
dev_err(&func->dev, "failed to enable func, error %d\n", error);
goto err_release_host;
}
sdio_release_host(func);
sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
if (!sdio) {
error = -ENOMEM;
dev_err(&func->dev, "failed to allocate ssb bus\n");
goto err_disable_func;
}
error = ssb_bus_sdiobus_register(&sdio->ssb, func,
b43_sdio_get_quirks(vendor, device));
if (error) {
dev_err(&func->dev, "failed to register ssb sdio bus,"
" error %d\n", error);
goto err_free_ssb;
}
sdio_set_drvdata(func, sdio);
return 0;
err_free_ssb:
kfree(sdio);
err_disable_func:
sdio_claim_host(func);
sdio_disable_func(func);
err_release_host:
sdio_release_host(func);
out:
return error;
}
static void b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
ssb_bus_unregister(&sdio->ssb);
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
kfree(sdio);
sdio_set_drvdata(func, NULL);
}
static const struct sdio_device_id b43_sdio_ids[] = {
{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
{ SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
{ },
};
static struct sdio_driver b43_sdio_driver = {
.name = "b43-sdio",
.id_table = b43_sdio_ids,
.probe = b43_sdio_probe,
.remove = b43_sdio_remove,
};
int b43_sdio_init(void)
{
return sdio_register_driver(&b43_sdio_driver);
}
void b43_sdio_exit(void)
{
sdio_unregister_driver(&b43_sdio_driver);
}

View File

@@ -0,0 +1,45 @@
#ifndef B43_SDIO_H_
#define B43_SDIO_H_
#include <linux/ssb/ssb.h>
struct b43_wldev;
#ifdef CONFIG_B43_SDIO
struct b43_sdio {
struct ssb_bus ssb;
void *irq_handler_opaque;
void (*irq_handler)(struct b43_wldev *dev);
};
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev));
void b43_sdio_free_irq(struct b43_wldev *dev);
int b43_sdio_init(void);
void b43_sdio_exit(void);
#else /* CONFIG_B43_SDIO */
static inline int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
return -ENODEV;
}
static inline void b43_sdio_free_irq(struct b43_wldev *dev)
{
}
static inline int b43_sdio_init(void)
{
return 0;
}
static inline void b43_sdio_exit(void)
{
}
#endif /* CONFIG_B43_SDIO */
#endif /* B43_SDIO_H_ */

View File

@@ -0,0 +1,155 @@
/*
Broadcom B43 wireless driver
SYSFS support routines
Copyright (c) 2006 Michael Buesch <m@bues.ch>
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/capability.h>
#include <linux/io.h>
#include "b43.h"
#include "sysfs.h"
#include "main.h"
#include "phy_common.h"
#define GENERIC_FILESIZE 64
static int get_integer(const char *buf, size_t count)
{
char tmp[10 + 1] = { 0 };
int ret = -EINVAL;
if (count == 0)
goto out;
count = min_t(size_t, count, 10);
memcpy(tmp, buf, count);
ret = simple_strtol(tmp, NULL, 10);
out:
return ret;
}
static ssize_t b43_attr_interfmode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct b43_wldev *wldev = dev_to_b43_wldev(dev);
ssize_t count = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mutex_lock(&wldev->wl->mutex);
if (wldev->phy.type != B43_PHYTYPE_G) {
mutex_unlock(&wldev->wl->mutex);
return -ENOSYS;
}
switch (wldev->phy.g->interfmode) {
case B43_INTERFMODE_NONE:
count =
snprintf(buf, PAGE_SIZE,
"0 (No Interference Mitigation)\n");
break;
case B43_INTERFMODE_NONWLAN:
count =
snprintf(buf, PAGE_SIZE,
"1 (Non-WLAN Interference Mitigation)\n");
break;
case B43_INTERFMODE_MANUALWLAN:
count =
snprintf(buf, PAGE_SIZE,
"2 (WLAN Interference Mitigation)\n");
break;
default:
B43_WARN_ON(1);
}
mutex_unlock(&wldev->wl->mutex);
return count;
}
static ssize_t b43_attr_interfmode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct b43_wldev *wldev = dev_to_b43_wldev(dev);
int err;
int mode;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mode = get_integer(buf, count);
switch (mode) {
case 0:
mode = B43_INTERFMODE_NONE;
break;
case 1:
mode = B43_INTERFMODE_NONWLAN;
break;
case 2:
mode = B43_INTERFMODE_MANUALWLAN;
break;
case 3:
mode = B43_INTERFMODE_AUTOWLAN;
break;
default:
return -EINVAL;
}
mutex_lock(&wldev->wl->mutex);
if (wldev->phy.ops->interf_mitigation) {
err = wldev->phy.ops->interf_mitigation(wldev, mode);
if (err) {
b43err(wldev->wl, "Interference Mitigation not "
"supported by device\n");
}
} else
err = -ENOSYS;
mmiowb();
mutex_unlock(&wldev->wl->mutex);
return err ? err : count;
}
static DEVICE_ATTR(interference, 0644,
b43_attr_interfmode_show, b43_attr_interfmode_store);
int b43_sysfs_register(struct b43_wldev *wldev)
{
struct device *dev = wldev->dev->dev;
B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
return device_create_file(dev, &dev_attr_interference);
}
void b43_sysfs_unregister(struct b43_wldev *wldev)
{
struct device *dev = wldev->dev->dev;
device_remove_file(dev, &dev_attr_interference);
}

View File

@@ -0,0 +1,9 @@
#ifndef B43_SYSFS_H_
#define B43_SYSFS_H_
struct b43_wldev;
int b43_sysfs_register(struct b43_wldev *dev);
void b43_sysfs_unregister(struct b43_wldev *dev);
#endif /* B43_SYSFS_H_ */

View File

@@ -0,0 +1,466 @@
/*
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2006, 2006 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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.h"
#include "phy_g.h"
const u32 b43_tab_rotor[] = {
0xFEB93FFD, 0xFEC63FFD, /* 0 */
0xFED23FFD, 0xFEDF3FFD,
0xFEEC3FFE, 0xFEF83FFE,
0xFF053FFE, 0xFF113FFE,
0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
0xFF373FFF, 0xFF443FFF,
0xFF503FFF, 0xFF5D3FFF,
0xFF693FFF, 0xFF763FFF,
0xFF824000, 0xFF8F4000, /* 16 */
0xFF9B4000, 0xFFA84000,
0xFFB54000, 0xFFC14000,
0xFFCE4000, 0xFFDA4000,
0xFFE74000, 0xFFF34000, /* 24 */
0x00004000, 0x000D4000,
0x00194000, 0x00264000,
0x00324000, 0x003F4000,
0x004B4000, 0x00584000, /* 32 */
0x00654000, 0x00714000,
0x007E4000, 0x008A3FFF,
0x00973FFF, 0x00A33FFF,
0x00B03FFF, 0x00BC3FFF, /* 40 */
0x00C93FFF, 0x00D63FFF,
0x00E23FFE, 0x00EF3FFE,
0x00FB3FFE, 0x01083FFE,
0x01143FFE, 0x01213FFD, /* 48 */
0x012E3FFD, 0x013A3FFD,
0x01473FFD,
};
const u32 b43_tab_retard[] = {
0xDB93CB87, 0xD666CF64, /* 0 */
0xD1FDD358, 0xCDA6D826,
0xCA38DD9F, 0xC729E2B4,
0xC469E88E, 0xC26AEE2B,
0xC0DEF46C, 0xC073FA62, /* 8 */
0xC01D00D5, 0xC0760743,
0xC1560D1E, 0xC2E51369,
0xC4ED18FF, 0xC7AC1ED7,
0xCB2823B2, 0xCEFA28D9, /* 16 */
0xD2F62D3F, 0xD7BB3197,
0xDCE53568, 0xE1FE3875,
0xE7D13B35, 0xED663D35,
0xF39B3EC4, 0xF98E3FA7, /* 24 */
0x00004000, 0x06723FA7,
0x0C653EC4, 0x129A3D35,
0x182F3B35, 0x1E023875,
0x231B3568, 0x28453197, /* 32 */
0x2D0A2D3F, 0x310628D9,
0x34D823B2, 0x38541ED7,
0x3B1318FF, 0x3D1B1369,
0x3EAA0D1E, 0x3F8A0743, /* 40 */
0x3FE300D5, 0x3F8DFA62,
0x3F22F46C, 0x3D96EE2B,
0x3B97E88E, 0x38D7E2B4,
0x35C8DD9F, 0x325AD826, /* 48 */
0x2E03D358, 0x299ACF64,
0x246DCB87,
};
const u16 b43_tab_finefreqa[] = {
0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
0x0202, 0x0282, 0x0302, 0x0382,
0x0402, 0x0482, 0x0502, 0x0582,
0x05E2, 0x0662, 0x06E2, 0x0762,
0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
0x09C2, 0x0A22, 0x0AA2, 0x0B02,
0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
0x0D42, 0x0DA2, 0x0E02, 0x0E62,
0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
0x1062, 0x10C2, 0x1122, 0x1182,
0x11E2, 0x1242, 0x12A2, 0x12E2,
0x1342, 0x13A2, 0x1402, 0x1442,
0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
0x15E2, 0x1622, 0x1662, 0x16C1,
0x1701, 0x1741, 0x1781, 0x17E1,
0x1821, 0x1861, 0x18A1, 0x18E1,
0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
0x1B01, 0x1B41, 0x1B81, 0x1BA1,
0x1BE1, 0x1C21, 0x1C41, 0x1C81,
0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
0x1E21, 0x1E61, 0x1E81, 0x1EA1,
0x1EE1, 0x1F01, 0x1F21, 0x1F41,
0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
0x2001, 0x2041, 0x2061, 0x2081,
0x20A1, 0x20C1, 0x20E1, 0x2101,
0x2121, 0x2141, 0x2161, 0x2181,
0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
0x2221, 0x2241, 0x2261, 0x2281,
0x22A1, 0x22C1, 0x22C1, 0x22E1,
0x2301, 0x2321, 0x2341, 0x2361,
0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
0x23E1, 0x23E1, 0x2401, 0x2421,
0x2441, 0x2441, 0x2461, 0x2481,
0x2481, 0x24A1, 0x24C1, 0x24C1,
0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
0x2541, 0x2541, 0x2561, 0x2561,
0x2581, 0x25A1, 0x25A1, 0x25C1,
0x25C1, 0x25E1, 0x2601, 0x2601,
0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
0x2661, 0x2661, 0x2681, 0x2681,
0x26A1, 0x26A1, 0x26C1, 0x26C1,
0x26E1, 0x26E1, 0x2701, 0x2701,
0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
0x2760, 0x2760, 0x2780, 0x2780,
0x2780, 0x27A0, 0x27A0, 0x27C0,
0x27C0, 0x27E0, 0x27E0, 0x27E0,
0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
0x2820, 0x2840, 0x2840, 0x2840,
0x2860, 0x2860, 0x2880, 0x2880,
0x2880, 0x28A0, 0x28A0, 0x28A0,
0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
0x28E0, 0x28E0, 0x2900, 0x2900,
0x2900, 0x2920, 0x2920, 0x2920,
0x2940, 0x2940, 0x2940, 0x2960,
0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
0x2980, 0x2980, 0x29A0, 0x29A0,
0x29A0, 0x29A0, 0x29C0, 0x29C0,
0x29C0, 0x29E0, 0x29E0, 0x29E0,
0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
0x2A00, 0x2A20, 0x2A20, 0x2A20,
0x2A20, 0x2A40, 0x2A40, 0x2A40,
0x2A40, 0x2A60, 0x2A60, 0x2A60,
};
const u16 b43_tab_finefreqg[] = {
0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
0x05A9, 0x0669, 0x0709, 0x0789,
0x0829, 0x08A9, 0x0929, 0x0989,
0x0A09, 0x0A69, 0x0AC9, 0x0B29,
0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
0x0D09, 0x0D69, 0x0DA9, 0x0E09,
0x0E69, 0x0EA9, 0x0F09, 0x0F49,
0x0FA9, 0x0FE9, 0x1029, 0x1089,
0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
0x11E9, 0x1229, 0x1289, 0x12C9,
0x1309, 0x1349, 0x1389, 0x13C9,
0x1409, 0x1449, 0x14A9, 0x14E9,
0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
0x1629, 0x1669, 0x16A9, 0x16E8,
0x1728, 0x1768, 0x17A8, 0x17E8,
0x1828, 0x1868, 0x18A8, 0x18E8,
0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
0x1E48, 0x1E88, 0x1EC8, 0x1F08,
0x1F48, 0x1F88, 0x1FE8, 0x2028,
0x2068, 0x20A8, 0x2108, 0x2148,
0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
0x22C8, 0x2308, 0x2348, 0x23A8,
0x23E8, 0x2448, 0x24A8, 0x24E8,
0x2548, 0x25A8, 0x2608, 0x2668,
0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
0x2847, 0x28C7, 0x2947, 0x29A7,
0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
0x2CA7, 0x2D67, 0x2E47, 0x2F67,
0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
0x3806, 0x38A6, 0x3946, 0x39E6,
0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
0x3C45, 0x3CA5, 0x3D05, 0x3D85,
0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
0x3F45, 0x3FA5, 0x4005, 0x4045,
0x40A5, 0x40E5, 0x4145, 0x4185,
0x41E5, 0x4225, 0x4265, 0x42C5,
0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
0x4424, 0x4464, 0x44C4, 0x4504,
0x4544, 0x4584, 0x45C4, 0x4604,
0x4644, 0x46A4, 0x46E4, 0x4724,
0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
0x4864, 0x48A4, 0x48E4, 0x4924,
0x4964, 0x49A4, 0x49E4, 0x4A24,
0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
0x5083, 0x50C3, 0x5103, 0x5143,
0x5183, 0x51E2, 0x5222, 0x5262,
0x52A2, 0x52E2, 0x5342, 0x5382,
0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
0x5502, 0x5542, 0x55A2, 0x55E2,
0x5642, 0x5682, 0x56E2, 0x5722,
0x5782, 0x57E1, 0x5841, 0x58A1,
0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
0x5C61, 0x5D01, 0x5D80, 0x5E20,
0x5EE0, 0x5FA0, 0x6080, 0x61C0,
};
const u16 b43_tab_noisea2[] = {
0x0001, 0x0001, 0x0001, 0xFFFE,
0xFFFE, 0x3FFF, 0x1000, 0x0393,
};
const u16 b43_tab_noisea3[] = {
0x5E5E, 0x5E5E, 0x5E5E, 0x3F48,
0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
};
const u16 b43_tab_noiseg1[] = {
0x013C, 0x01F5, 0x031A, 0x0631,
0x0001, 0x0001, 0x0001, 0x0001,
};
const u16 b43_tab_noiseg2[] = {
0x5484, 0x3C40, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
};
const u16 b43_tab_noisescalea2[] = {
0x6767, 0x6767, 0x6767, 0x6767, /* 0 */
0x6767, 0x6767, 0x6767, 0x6767,
0x6767, 0x6767, 0x6767, 0x6767,
0x6767, 0x6700, 0x6767, 0x6767,
0x6767, 0x6767, 0x6767, 0x6767, /* 16 */
0x6767, 0x6767, 0x6767, 0x6767,
0x6767, 0x6767, 0x0067,
};
const u16 b43_tab_noisescalea3[] = {
0x2323, 0x2323, 0x2323, 0x2323, /* 0 */
0x2323, 0x2323, 0x2323, 0x2323,
0x2323, 0x2323, 0x2323, 0x2323,
0x2323, 0x2300, 0x2323, 0x2323,
0x2323, 0x2323, 0x2323, 0x2323, /* 16 */
0x2323, 0x2323, 0x2323, 0x2323,
0x2323, 0x2323, 0x0023,
};
const u16 b43_tab_noisescaleg1[] = {
0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
0x2F2D, 0x2A2A, 0x2527, 0x1F21,
0x1A1D, 0x1719, 0x1616, 0x1414,
0x1414, 0x1400, 0x1414, 0x1614,
0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
0x2A27, 0x2F2A, 0x332D, 0x3B35,
0x5140, 0x6C62, 0x0077,
};
const u16 b43_tab_noisescaleg2[] = {
0xD8DD, 0xCBD4, 0xBCC0, 0xB6B7, /* 0 */
0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
0x969B, 0x9195, 0x8F8F, 0x8A8A,
0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
0xCBC0, 0xD8D4, 0x00DD,
};
const u16 b43_tab_noisescaleg3[] = {
0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
0xA4A4, 0xA4A4, 0x00A4,
};
const u16 b43_tab_sigmasqr1[] = {
0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
0x0067, 0x0063, 0x005E, 0x0059,
0x0054, 0x0050, 0x004B, 0x0046,
0x0042, 0x003D, 0x003D, 0x003D,
0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
0x003D, 0x003D, 0x003D, 0x003D,
0x003D, 0x003D, 0x0000, 0x003D,
0x003D, 0x003D, 0x003D, 0x003D,
0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
0x003D, 0x003D, 0x003D, 0x003D,
0x0042, 0x0046, 0x004B, 0x0050,
0x0054, 0x0059, 0x005E, 0x0063,
0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
0x007A,
};
const u16 b43_tab_sigmasqr2[] = {
0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
0x00D6, 0x00D4, 0x00D2, 0x00CF,
0x00CD, 0x00CA, 0x00C7, 0x00C4,
0x00C1, 0x00BE, 0x00BE, 0x00BE,
0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
0x00BE, 0x00BE, 0x00BE, 0x00BE,
0x00BE, 0x00BE, 0x0000, 0x00BE,
0x00BE, 0x00BE, 0x00BE, 0x00BE,
0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
0x00BE, 0x00BE, 0x00BE, 0x00BE,
0x00C1, 0x00C4, 0x00C7, 0x00CA,
0x00CD, 0x00CF, 0x00D2, 0x00D4,
0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
0x00DE,
};
const u16 b43_tab_rssiagc1[] = {
0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, /* 0 */
0xFFF8, 0xFFF9, 0xFFFC, 0xFFFE,
0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
};
const u16 b43_tab_rssiagc2[] = {
0x0820, 0x0820, 0x0920, 0x0C38, /* 0 */
0x0820, 0x0820, 0x0820, 0x0820,
0x0820, 0x0820, 0x0920, 0x0A38,
0x0820, 0x0820, 0x0820, 0x0820,
0x0820, 0x0820, 0x0920, 0x0A38, /* 16 */
0x0820, 0x0820, 0x0820, 0x0820,
0x0820, 0x0820, 0x0920, 0x0A38,
0x0820, 0x0820, 0x0820, 0x0820,
0x0820, 0x0820, 0x0920, 0x0A38, /* 32 */
0x0820, 0x0820, 0x0820, 0x0820,
0x0820, 0x0820, 0x0920, 0x0A38,
0x0820, 0x0820, 0x0820, 0x0820,
};
static inline void assert_sizes(void)
{
BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor));
BUILD_BUG_ON(B43_TAB_RETARD_SIZE != ARRAY_SIZE(b43_tab_retard));
BUILD_BUG_ON(B43_TAB_FINEFREQA_SIZE != ARRAY_SIZE(b43_tab_finefreqa));
BUILD_BUG_ON(B43_TAB_FINEFREQG_SIZE != ARRAY_SIZE(b43_tab_finefreqg));
BUILD_BUG_ON(B43_TAB_NOISEA2_SIZE != ARRAY_SIZE(b43_tab_noisea2));
BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3));
BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1));
BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2));
BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescalea2));
BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescalea3));
BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg1));
BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg2));
BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg3));
BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1));
BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2));
BUILD_BUG_ON(B43_TAB_RSSIAGC1_SIZE != ARRAY_SIZE(b43_tab_rssiagc1));
BUILD_BUG_ON(B43_TAB_RSSIAGC2_SIZE != ARRAY_SIZE(b43_tab_rssiagc2));
}
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
{
struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
(addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
}
gphy->ofdmtab_addr = addr;
return b43_phy_read(dev, B43_PHY_OTABLEI);
/* Some compiletime assertions... */
assert_sizes();
}
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
u16 offset, u16 value)
{
struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
(addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
}
gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value);
}
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
{
struct b43_phy_g *gphy = dev->phy.g;
u32 ret;
u16 addr;
addr = table + offset;
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
(addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
}
gphy->ofdmtab_addr = addr;
ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
ret <<= 16;
ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
return ret;
}
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
u16 offset, u32 value)
{
struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
(addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
}
gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value);
b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
}
u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset)
{
b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
return b43_phy_read(dev, B43_PHY_GTABDATA);
}
void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value)
{
b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
b43_phy_write(dev, B43_PHY_GTABDATA, value);
}

View File

@@ -0,0 +1,34 @@
#ifndef B43_TABLES_H_
#define B43_TABLES_H_
#define B43_TAB_ROTOR_SIZE 53
extern const u32 b43_tab_rotor[];
#define B43_TAB_RETARD_SIZE 53
extern const u32 b43_tab_retard[];
#define B43_TAB_FINEFREQA_SIZE 256
extern const u16 b43_tab_finefreqa[];
#define B43_TAB_FINEFREQG_SIZE 256
extern const u16 b43_tab_finefreqg[];
#define B43_TAB_NOISEA2_SIZE 8
extern const u16 b43_tab_noisea2[];
#define B43_TAB_NOISEA3_SIZE 8
extern const u16 b43_tab_noisea3[];
#define B43_TAB_NOISEG1_SIZE 8
extern const u16 b43_tab_noiseg1[];
#define B43_TAB_NOISEG2_SIZE 8
extern const u16 b43_tab_noiseg2[];
#define B43_TAB_NOISESCALE_SIZE 27
extern const u16 b43_tab_noisescalea2[];
extern const u16 b43_tab_noisescalea3[];
extern const u16 b43_tab_noisescaleg1[];
extern const u16 b43_tab_noisescaleg2[];
extern const u16 b43_tab_noisescaleg3[];
#define B43_TAB_SIGMASQR_SIZE 53
extern const u16 b43_tab_sigmasqr1[];
extern const u16 b43_tab_sigmasqr2[];
#define B43_TAB_RSSIAGC1_SIZE 16
extern const u16 b43_tab_rssiagc1[];
#define B43_TAB_RSSIAGC2_SIZE 48
extern const u16 b43_tab_rssiagc2[];
#endif /* B43_TABLES_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
#ifndef B43_TABLES_LPPHY_H_
#define B43_TABLES_LPPHY_H_
#define B43_LPTAB_TYPEMASK 0xF0000000
#define B43_LPTAB_8BIT 0x10000000
#define B43_LPTAB_16BIT 0x20000000
#define B43_LPTAB_32BIT 0x30000000
#define B43_LPTAB8(table, offset) (((table) << 10) | (offset) | B43_LPTAB_8BIT)
#define B43_LPTAB16(table, offset) (((table) << 10) | (offset) | B43_LPTAB_16BIT)
#define B43_LPTAB32(table, offset) (((table) << 10) | (offset) | B43_LPTAB_32BIT)
/* Table definitions */
#define B43_LPTAB_TXPWR_R2PLUS B43_LPTAB32(0x07, 0) /* TX power lookup table (rev >= 2) */
#define B43_LPTAB_TXPWR_R0_1 B43_LPTAB32(0xA0, 0) /* TX power lookup table (rev < 2) */
u32 b43_lptab_read(struct b43_wldev *dev, u32 offset);
void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value);
/* Bulk table access. Note that these functions return the bulk data in
* host endianness! The returned data is _not_ a bytearray, but an array
* consisting of nr_elements of the data type. */
void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *data);
void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *data);
void b2062_upload_init_table(struct b43_wldev *dev);
void b2063_upload_init_table(struct b43_wldev *dev);
struct lpphy_tx_gain_table_entry {
u8 gm, pga, pad, dac, bb_mult;
};
void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
struct lpphy_tx_gain_table_entry data);
void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
struct lpphy_tx_gain_table_entry *table);
void lpphy_rev0_1_table_init(struct b43_wldev *dev);
void lpphy_rev2plus_table_init(struct b43_wldev *dev);
void lpphy_init_tx_gain_table(struct b43_wldev *dev);
#endif /* B43_TABLES_LPPHY_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,222 @@
#ifndef B43_TABLES_NPHY_H_
#define B43_TABLES_NPHY_H_
#include <linux/types.h>
struct b43_phy_n_sfo_cfg {
u16 phy_bw1a;
u16 phy_bw2;
u16 phy_bw3;
u16 phy_bw4;
u16 phy_bw5;
u16 phy_bw6;
};
struct b43_wldev;
struct nphy_txiqcal_ladder {
u8 percent;
u8 g_env;
};
struct nphy_rf_control_override_rev2 {
u8 addr0;
u8 addr1;
u16 bmask;
u8 shift;
};
struct nphy_rf_control_override_rev3 {
u16 val_mask;
u8 val_shift;
u8 en_addr0;
u8 val_addr0;
u8 en_addr1;
u8 val_addr1;
};
struct nphy_rf_control_override_rev7 {
u16 field;
u16 val_addr_core0;
u16 val_addr_core1;
u16 val_mask;
u8 val_shift;
};
struct nphy_gain_ctl_workaround_entry {
s8 lna1_gain[4];
s8 lna2_gain[4];
u8 gain_db[10];
u8 gain_bits[10];
u16 init_gain;
u16 rfseq_init[4];
u16 cliphi_gain;
u16 clipmd_gain;
u16 cliplo_gain;
u16 crsmin;
u16 crsminl;
u16 crsminu;
u16 nbclip;
u16 wlclip;
};
/* Get entry with workaround values for gain ctl. Does not return NULL. */
struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
struct b43_wldev *dev, bool ghz5, bool ext_lna);
/* The N-PHY tables. */
#define B43_NTAB_TYPEMASK 0xF0000000
#define B43_NTAB_8BIT 0x10000000
#define B43_NTAB_16BIT 0x20000000
#define B43_NTAB_32BIT 0x30000000
#define B43_NTAB8(table, offset) (((table) << 10) | (offset) | B43_NTAB_8BIT)
#define B43_NTAB16(table, offset) (((table) << 10) | (offset) | B43_NTAB_16BIT)
#define B43_NTAB32(table, offset) (((table) << 10) | (offset) | B43_NTAB_32BIT)
/* Static N-PHY tables */
#define B43_NTAB_FRAMESTRUCT B43_NTAB32(0x0A, 0x000) /* Frame Struct Table */
#define B43_NTAB_FRAMESTRUCT_SIZE 832
#define B43_NTAB_FRAMELT B43_NTAB8 (0x18, 0x000) /* Frame Lookup Table */
#define B43_NTAB_FRAMELT_SIZE 32
#define B43_NTAB_TMAP B43_NTAB32(0x0C, 0x000) /* T Map Table */
#define B43_NTAB_TMAP_SIZE 448
#define B43_NTAB_TDTRN B43_NTAB32(0x0E, 0x000) /* TDTRN Table */
#define B43_NTAB_TDTRN_SIZE 704
#define B43_NTAB_INTLEVEL B43_NTAB32(0x0D, 0x000) /* Int Level Table */
#define B43_NTAB_INTLEVEL_SIZE 7
#define B43_NTAB_PILOT B43_NTAB16(0x0B, 0x000) /* Pilot Table */
#define B43_NTAB_PILOT_SIZE 88
#define B43_NTAB_PILOTLT B43_NTAB32(0x14, 0x000) /* Pilot Lookup Table */
#define B43_NTAB_PILOTLT_SIZE 6
#define B43_NTAB_TDI20A0 B43_NTAB32(0x13, 0x080) /* TDI Table 20 Antenna 0 */
#define B43_NTAB_TDI20A0_SIZE 55
#define B43_NTAB_TDI20A1 B43_NTAB32(0x13, 0x100) /* TDI Table 20 Antenna 1 */
#define B43_NTAB_TDI20A1_SIZE 55
#define B43_NTAB_TDI40A0 B43_NTAB32(0x13, 0x280) /* TDI Table 40 Antenna 0 */
#define B43_NTAB_TDI40A0_SIZE 110
#define B43_NTAB_TDI40A1 B43_NTAB32(0x13, 0x300) /* TDI Table 40 Antenna 1 */
#define B43_NTAB_TDI40A1_SIZE 110
#define B43_NTAB_BDI B43_NTAB16(0x15, 0x000) /* BDI Table */
#define B43_NTAB_BDI_SIZE 6
#define B43_NTAB_CHANEST B43_NTAB32(0x16, 0x000) /* Channel Estimate Table */
#define B43_NTAB_CHANEST_SIZE 96
#define B43_NTAB_MCS B43_NTAB8 (0x12, 0x000) /* MCS Table */
#define B43_NTAB_MCS_SIZE 128
/* Volatile N-PHY tables */
#define B43_NTAB_NOISEVAR10 B43_NTAB32(0x10, 0x000) /* Noise Var Table 10 */
#define B43_NTAB_NOISEVAR10_SIZE 256
#define B43_NTAB_NOISEVAR11 B43_NTAB32(0x10, 0x080) /* Noise Var Table 11 */
#define B43_NTAB_NOISEVAR11_SIZE 256
#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
#define B43_NTAB_C0_ESTPLT_SIZE 64
#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
#define B43_NTAB_C0_ADJPLT_SIZE 128
#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
#define B43_NTAB_C0_GAINCTL_SIZE 128
#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
#define B43_NTAB_C0_IQLT_SIZE 128
#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
#define B43_NTAB_C0_LOFEEDTH_SIZE 128
#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
#define B43_NTAB_C1_ESTPLT_SIZE 64
#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
#define B43_NTAB_C1_ADJPLT_SIZE 128
#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
#define B43_NTAB_C1_GAINCTL_SIZE 128
#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
#define B43_NTAB_C1_IQLT_SIZE 128
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
/* Volatile N-PHY tables, PHY revision >= 3 */
#define B43_NTAB_ANT_SW_CTL_R3 B43_NTAB16( 9, 0) /* antenna software control */
/* Static N-PHY tables, PHY revision >= 3 */
#define B43_NTAB_FRAMESTRUCT_R3 B43_NTAB32(10, 0) /* frame struct */
#define B43_NTAB_PILOT_R3 B43_NTAB16(11, 0) /* pilot */
#define B43_NTAB_TMAP_R3 B43_NTAB32(12, 0) /* TM AP */
#define B43_NTAB_INTLEVEL_R3 B43_NTAB32(13, 0) /* INT LV */
#define B43_NTAB_TDTRN_R3 B43_NTAB32(14, 0) /* TD TRN */
#define B43_NTAB_NOISEVAR_R3 B43_NTAB32(16, 0) /* noise variance */
#define B43_NTAB_MCS_R3 B43_NTAB16(18, 0) /* MCS */
#define B43_NTAB_TDI20A0_R3 B43_NTAB32(19, 128) /* TDI 20/0 */
#define B43_NTAB_TDI20A1_R3 B43_NTAB32(19, 256) /* TDI 20/1 */
#define B43_NTAB_TDI40A0_R3 B43_NTAB32(19, 640) /* TDI 40/0 */
#define B43_NTAB_TDI40A1_R3 B43_NTAB32(19, 768) /* TDI 40/1 */
#define B43_NTAB_PILOTLT_R3 B43_NTAB32(20, 0) /* PLT lookup */
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */
#define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */
#define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */
#define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */
#define B43_NTAB_C0_LOFEEDTH_R3 B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0 */
#define B43_NTAB_C0_PAPD_COMP_R3 B43_NTAB16(26, 576)
#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
/* Static N-PHY tables, PHY revision >= 7 */
#define B43_NTAB_TMAP_R7 B43_NTAB32(12, 0) /* TM AP */
#define B43_NTAB_NOISEVAR_R7 B43_NTAB32(16, 0) /* noise variance */
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_20_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3 11
#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS 9
#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3 12
#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL 10
#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10
#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12
u32 b43_ntab_read(struct b43_wldev *dev, u32 offset);
void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_nphy_tables_init(struct b43_wldev *dev);
const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
const s16 *b43_ntab_get_rf_pwr_offset_table(struct b43_wldev *dev);
extern const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[];
extern const u16 tbl_iqcal_gainparams[2][9][8];
extern const struct nphy_txiqcal_ladder ladder_lo[];
extern const struct nphy_txiqcal_ladder ladder_iq[];
extern const u16 loscale[];
extern const u16 tbl_tx_iqlo_cal_loft_ladder_40[];
extern const u16 tbl_tx_iqlo_cal_loft_ladder_20[];
extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[];
extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[];
extern const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[];
extern const u16 tbl_tx_iqlo_cal_startcoefs[];
extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[];
extern const u16 tbl_tx_iqlo_cal_cmds_recal[];
extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[];
extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[];
extern const s16 tbl_tx_filter_coef_rev4[7][15];
extern const struct nphy_rf_control_override_rev2
tbl_rf_control_override_rev2[];
extern const struct nphy_rf_control_override_rev3
tbl_rf_control_override_rev3[];
const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
struct b43_wldev *dev, u16 field, u8 override);
#endif /* B43_TABLES_NPHY_H_ */

View File

@@ -0,0 +1,836 @@
/*
Broadcom B43 wireless driver
IEEE 802.11n HT-PHY data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
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_ht.h"
#include "phy_common.h"
#include "phy_ht.h"
static const u16 b43_httab_0x12[] = {
0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
0x0007, 0x0007,
};
static const u16 b43_httab_0x27[] = {
0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
0x001d, 0x0020,
};
static const u16 b43_httab_0x26[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000,
};
static const u32 b43_httab_0x25[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const u32 b43_httab_0x2f[] = {
0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
0x0001581f, 0x0001581f,
};
static const u16 b43_httab_0x1a[] = {
0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
0x000b, 0x0007, 0x0002, 0x00fd,
};
static const u16 b43_httab_0x1b[] = {
0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
0x000b, 0x0007, 0x0002, 0x00fd,
};
static const u16 b43_httab_0x1c[] = {
0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
0x000b, 0x0007, 0x0002, 0x00fd,
};
static const u32 b43_httab_0x1a_0xc0[] = {
0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
};
static const u32 b43_httab_0x1a_0x140[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const u32 b43_httab_0x1b_0x140[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const u32 b43_httab_0x1c_0x140[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const u16 b43_httab_0x1a_0x1c0[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000,
};
static const u16 b43_httab_0x1b_0x1c0[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000,
};
static const u16 b43_httab_0x1c_0x1c0[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000,
};
static const u16 b43_httab_0x1a_0x240[] = {
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6,
};
static const u16 b43_httab_0x1b_0x240[] = {
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6,
};
static const u16 b43_httab_0x1c_0x240[] = {
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
0x01d6, 0x01d6,
};
static const u32 b43_httab_0x1f[] = {
0x00000000, 0x00000000, 0x00016023, 0x00006028,
0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
};
static const u32 b43_httab_0x21[] = {
0x00000000, 0x00000000, 0x00016023, 0x00006028,
0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
};
static const u32 b43_httab_0x23[] = {
0x00000000, 0x00000000, 0x00016023, 0x00006028,
0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
};
static const u32 b43_httab_0x20[] = {
0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
};
static const u32 b43_httab_0x22[] = {
0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
};
static const u32 b43_httab_0x24[] = {
0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
};
/* Some late-init table */
const u32 b43_httab_0x1a_0xc0_late[] = {
0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
0x10390038, 0x10390035, 0x1031003a, 0x10310036,
0x10310033, 0x1029003a, 0x10290037, 0x10290034,
0x10290031, 0x10210039, 0x10210036, 0x10210033,
0x10210030, 0x1019003c, 0x10190039, 0x10190036,
0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
0x10190028, 0x1011003a, 0x10110036, 0x10110033,
0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
0x10110027, 0x10110024, 0x10110022, 0x10110020,
0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
0x10090029, 0x10090027, 0x10090025, 0x10090023,
0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
0x1009001a, 0x10090018, 0x10090017, 0x10090016,
0x10090015, 0x10090013, 0x10090012, 0x10090011,
0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
0x10090008, 0x10090008, 0x10090007, 0x10090007,
0x10090007, 0x10090006, 0x10090006, 0x10090005,
0x10090005, 0x10090005, 0x10090005, 0x10090004,
0x10090004, 0x10090004, 0x10090004, 0x10090003,
0x10090003, 0x10090003, 0x10090003, 0x10090003,
0x10090003, 0x10090002, 0x10090002, 0x10090002,
0x10090002, 0x10090002, 0x10090002, 0x10090002,
0x10090002, 0x10090002, 0x10090001, 0x10090001,
0x10090001, 0x10090001, 0x10090001, 0x10090001,
};
/**************************************************
* R/W ops.
**************************************************/
u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
{
u32 type, value;
type = offset & B43_HTTAB_TYPEMASK;
offset &= ~B43_HTTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
switch (type) {
case B43_HTTAB_8BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
break;
case B43_HTTAB_16BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
break;
case B43_HTTAB_32BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
value <<= 16;
value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
break;
default:
B43_WARN_ON(1);
value = 0;
}
return value;
}
void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data)
{
u32 type;
u8 *data = _data;
unsigned int i;
type = offset & B43_HTTAB_TYPEMASK;
offset &= ~B43_HTTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
switch (type) {
case B43_HTTAB_8BIT:
*data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
data++;
break;
case B43_HTTAB_16BIT:
*((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
data += 2;
break;
case B43_HTTAB_32BIT:
*((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
*((u32 *)data) <<= 16;
*((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
data += 4;
break;
default:
B43_WARN_ON(1);
}
}
}
void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
{
u32 type;
type = offset & B43_HTTAB_TYPEMASK;
offset &= 0xFFFF;
switch (type) {
case B43_HTTAB_8BIT:
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
break;
case B43_HTTAB_16BIT:
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
break;
case B43_HTTAB_32BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF);
break;
default:
B43_WARN_ON(1);
}
return;
}
void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...)
{
va_list args;
u32 type, value;
unsigned int i;
type = offset & B43_HTTAB_TYPEMASK;
offset &= 0xFFFF;
va_start(args, num);
switch (type) {
case B43_HTTAB_8BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
}
break;
case B43_HTTAB_16BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
}
break;
case B43_HTTAB_32BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI,
value >> 16);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
value & 0xFFFF);
}
break;
default:
B43_WARN_ON(1);
}
va_end(args);
return;
}
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data)
{
u32 type, value;
const u8 *data = _data;
unsigned int i;
type = offset & B43_HTTAB_TYPEMASK;
offset &= ~B43_HTTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
switch (type) {
case B43_HTTAB_8BIT:
value = *data;
data++;
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
break;
case B43_HTTAB_16BIT:
value = *((u16 *)data);
data += 2;
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
break;
case B43_HTTAB_32BIT:
value = *((u32 *)data);
data += 4;
b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
value & 0xFFFF);
break;
default:
B43_WARN_ON(1);
}
}
}
/**************************************************
* Tables ops.
**************************************************/
#define httab_upload(dev, offset, data) do { \
b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
void b43_phy_ht_tables_init(struct b43_wldev *dev)
{
BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) !=
B43_HTTAB_1A_C0_LATE_SIZE);
httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
}

View File

@@ -0,0 +1,26 @@
#ifndef B43_TABLES_PHY_HT_H_
#define B43_TABLES_PHY_HT_H_
/* The HT-PHY tables. */
#define B43_HTTAB_TYPEMASK 0xF0000000
#define B43_HTTAB_8BIT 0x10000000
#define B43_HTTAB_16BIT 0x20000000
#define B43_HTTAB_32BIT 0x30000000
#define B43_HTTAB8(table, offset) (((table) << 10) | (offset) | B43_HTTAB_8BIT)
#define B43_HTTAB16(table, offset) (((table) << 10) | (offset) | B43_HTTAB_16BIT)
#define B43_HTTAB32(table, offset) (((table) << 10) | (offset) | B43_HTTAB_32BIT)
u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...);
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_phy_ht_tables_init(struct b43_wldev *dev);
#define B43_HTTAB_1A_C0_LATE_SIZE 128
extern const u32 b43_httab_0x1a_0xc0_late[];
#endif /* B43_TABLES_PHY_HT_H_ */

View File

@@ -0,0 +1,724 @@
/*
Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
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"
struct b43_lcntab_tx_gain_tbl_entry {
u8 gm;
u8 pga;
u8 pad;
u8 dac;
u8 bb_mult;
};
/**************************************************
* Static tables.
**************************************************/
static const u16 b43_lcntab_0x02[] = {
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d,
};
static const u16 b43_lcntab_0x01[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
};
static const u32 b43_lcntab_0x0b[] = {
0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
0x0001fea3, 0x0000024b,
};
static const u32 b43_lcntab_0x0c[] = {
0x00100001, 0x00200010, 0x00300001, 0x00400010,
0x00500022, 0x00600122, 0x00700222, 0x00800322,
0x00900422, 0x00a00522, 0x00b00622, 0x00c00722,
0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22,
0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22,
};
static const u32 b43_lcntab_0x0d[] = {
0x00000000, 0x00000000, 0x10000000, 0x00000000,
0x20000000, 0x00000000, 0x30000000, 0x00000000,
0x40000000, 0x00000000, 0x50000000, 0x00000000,
0x60000000, 0x00000000, 0x70000000, 0x00000000,
0x80000000, 0x00000000, 0x90000000, 0x00000008,
0xa0000000, 0x00000008, 0xb0000000, 0x00000008,
0xc0000000, 0x00000008, 0xd0000000, 0x00000008,
0xe0000000, 0x00000008, 0xf0000000, 0x00000008,
0x00000000, 0x00000009, 0x10000000, 0x00000009,
0x20000000, 0x00000019, 0x30000000, 0x00000019,
0x40000000, 0x00000019, 0x50000000, 0x00000019,
0x60000000, 0x00000019, 0x70000000, 0x00000019,
0x80000000, 0x00000019, 0x90000000, 0x00000019,
0xa0000000, 0x00000019, 0xb0000000, 0x00000019,
0xc0000000, 0x00000019, 0xd0000000, 0x00000019,
0xe0000000, 0x00000019, 0xf0000000, 0x00000019,
0x00000000, 0x0000001a, 0x10000000, 0x0000001a,
0x20000000, 0x0000001a, 0x30000000, 0x0000001a,
0x40000000, 0x0000001a, 0x50000000, 0x00000002,
0x60000000, 0x00000002, 0x70000000, 0x00000002,
0x80000000, 0x00000002, 0x90000000, 0x00000002,
0xa0000000, 0x00000002, 0xb0000000, 0x00000002,
0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a,
0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a,
0x00000000, 0x0000000b, 0x10000000, 0x0000000b,
0x20000000, 0x0000000b, 0x30000000, 0x0000000b,
0x40000000, 0x0000000b, 0x50000000, 0x0000001b,
0x60000000, 0x0000001b, 0x70000000, 0x0000001b,
0x80000000, 0x0000001b, 0x90000000, 0x0000001b,
0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b,
0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b,
0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b,
0x00000000, 0x0000001c, 0x10000000, 0x0000001c,
0x20000000, 0x0000001c, 0x30000000, 0x0000001c,
0x40000000, 0x0000001c, 0x50000000, 0x0000001c,
0x60000000, 0x0000001c, 0x70000000, 0x0000001c,
0x80000000, 0x0000001c, 0x90000000, 0x0000001c,
};
static const u16 b43_lcntab_0x0e[] = {
0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c,
0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092,
0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198,
0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4,
0x01a5, 0x0000,
};
static const u16 b43_lcntab_0x0f[] = {
0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
0x000a, 0x0009, 0x0006, 0x0005,
};
static const u16 b43_lcntab_0x10[] = {
0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036,
0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f,
0x005f, 0x0036, 0x0029, 0x001f,
};
static const u16 b43_lcntab_0x11[] = {
0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007,
0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005,
0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f,
0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000,
};
static const u32 b43_lcntab_0x12[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000004, 0x00000000, 0x00000004, 0x00000008,
0x00000001, 0x00000005, 0x00000009, 0x0000000d,
0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d,
0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f,
0x000000cf, 0x000000d3, 0x00000113, 0x00000513,
0x00000913, 0x00000953, 0x00000d53, 0x00001153,
0x00001193, 0x00005193, 0x00009193, 0x0000d193,
0x00011193, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000004,
0x00000000, 0x00000004, 0x00000008, 0x00000001,
0x00000005, 0x00000009, 0x0000000d, 0x0000004d,
0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d,
0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf,
0x000000d3, 0x00000113, 0x00000513, 0x00000913,
0x00000953, 0x00000d53, 0x00001153, 0x00005153,
0x00009153, 0x0000d153, 0x00011153, 0x00015153,
0x00019153, 0x0001d153, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
static const u16 b43_lcntab_0x14[] = {
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003,
0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001,
};
static const u16 b43_lcntab_0x17[] = {
0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0,
0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0,
0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c,
0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c,
0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340,
0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104,
0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104,
0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186,
0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104,
0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4,
0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186,
0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be,
0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036,
0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6,
0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288,
0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6,
0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8,
0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798,
0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6,
0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288,
0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a,
0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288,
0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360,
0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc,
0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510,
0x05b2, 0x0654, 0x0654, 0x06f6,
};
static const u16 b43_lcntab_0x00[] = {
0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00,
0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005,
0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003,
0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007,
0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
static const u32 b43_lcntab_0x18[] = {
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
0x00080000, 0x00080000, 0x00080000, 0x00080000,
};
/**************************************************
* TX gain.
**************************************************/
static const struct b43_lcntab_tx_gain_tbl_entry
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
{ 0x03, 0x00, 0x1f, 0x0, 0x44 },
{ 0x03, 0x00, 0x1e, 0x0, 0x43 },
{ 0x03, 0x00, 0x1d, 0x0, 0x44 },
{ 0x03, 0x00, 0x1c, 0x0, 0x44 },
{ 0x03, 0x00, 0x1b, 0x0, 0x45 },
{ 0x03, 0x00, 0x1a, 0x0, 0x46 },
{ 0x03, 0x00, 0x19, 0x0, 0x46 },
{ 0x03, 0x00, 0x18, 0x0, 0x47 },
{ 0x03, 0x00, 0x17, 0x0, 0x48 },
{ 0x03, 0x00, 0x17, 0x0, 0x46 },
{ 0x03, 0x00, 0x16, 0x0, 0x47 },
{ 0x03, 0x00, 0x15, 0x0, 0x48 },
{ 0x03, 0x00, 0x15, 0x0, 0x46 },
{ 0x03, 0x00, 0x15, 0x0, 0x44 },
{ 0x03, 0x00, 0x15, 0x0, 0x42 },
{ 0x03, 0x00, 0x15, 0x0, 0x40 },
{ 0x03, 0x00, 0x15, 0x0, 0x3f },
{ 0x03, 0x00, 0x14, 0x0, 0x40 },
{ 0x03, 0x00, 0x13, 0x0, 0x41 },
{ 0x03, 0x00, 0x13, 0x0, 0x40 },
{ 0x03, 0x00, 0x12, 0x0, 0x41 },
{ 0x03, 0x00, 0x12, 0x0, 0x40 },
{ 0x03, 0x00, 0x11, 0x0, 0x41 },
{ 0x03, 0x00, 0x11, 0x0, 0x40 },
{ 0x03, 0x00, 0x10, 0x0, 0x41 },
{ 0x03, 0x00, 0x10, 0x0, 0x40 },
{ 0x03, 0x00, 0x10, 0x0, 0x3e },
{ 0x03, 0x00, 0x10, 0x0, 0x3c },
{ 0x03, 0x00, 0x10, 0x0, 0x3a },
{ 0x03, 0x00, 0x0f, 0x0, 0x3d },
{ 0x03, 0x00, 0x0f, 0x0, 0x3b },
{ 0x03, 0x00, 0x0e, 0x0, 0x3d },
{ 0x03, 0x00, 0x0e, 0x0, 0x3c },
{ 0x03, 0x00, 0x0e, 0x0, 0x3a },
{ 0x03, 0x00, 0x0d, 0x0, 0x3c },
{ 0x03, 0x00, 0x0d, 0x0, 0x3b },
{ 0x03, 0x00, 0x0c, 0x0, 0x3e },
{ 0x03, 0x00, 0x0c, 0x0, 0x3c },
{ 0x03, 0x00, 0x0c, 0x0, 0x3a },
{ 0x03, 0x00, 0x0b, 0x0, 0x3e },
{ 0x03, 0x00, 0x0b, 0x0, 0x3c },
{ 0x03, 0x00, 0x0b, 0x0, 0x3b },
{ 0x03, 0x00, 0x0b, 0x0, 0x39 },
{ 0x03, 0x00, 0x0a, 0x0, 0x3d },
{ 0x03, 0x00, 0x0a, 0x0, 0x3b },
{ 0x03, 0x00, 0x0a, 0x0, 0x39 },
{ 0x03, 0x00, 0x09, 0x0, 0x3e },
{ 0x03, 0x00, 0x09, 0x0, 0x3c },
{ 0x03, 0x00, 0x09, 0x0, 0x3a },
{ 0x03, 0x00, 0x09, 0x0, 0x39 },
{ 0x03, 0x00, 0x08, 0x0, 0x3e },
{ 0x03, 0x00, 0x08, 0x0, 0x3c },
{ 0x03, 0x00, 0x08, 0x0, 0x3a },
{ 0x03, 0x00, 0x08, 0x0, 0x39 },
{ 0x03, 0x00, 0x08, 0x0, 0x37 },
{ 0x03, 0x00, 0x07, 0x0, 0x3d },
{ 0x03, 0x00, 0x07, 0x0, 0x3c },
{ 0x03, 0x00, 0x07, 0x0, 0x3a },
{ 0x03, 0x00, 0x07, 0x0, 0x38 },
{ 0x03, 0x00, 0x07, 0x0, 0x37 },
{ 0x03, 0x00, 0x06, 0x0, 0x3e },
{ 0x03, 0x00, 0x06, 0x0, 0x3c },
{ 0x03, 0x00, 0x06, 0x0, 0x3a },
{ 0x03, 0x00, 0x06, 0x0, 0x39 },
{ 0x03, 0x00, 0x06, 0x0, 0x37 },
{ 0x03, 0x00, 0x06, 0x0, 0x36 },
{ 0x03, 0x00, 0x06, 0x0, 0x34 },
{ 0x03, 0x00, 0x05, 0x0, 0x3d },
{ 0x03, 0x00, 0x05, 0x0, 0x3b },
{ 0x03, 0x00, 0x05, 0x0, 0x39 },
{ 0x03, 0x00, 0x05, 0x0, 0x38 },
{ 0x03, 0x00, 0x05, 0x0, 0x36 },
{ 0x03, 0x00, 0x05, 0x0, 0x35 },
{ 0x03, 0x00, 0x05, 0x0, 0x33 },
{ 0x03, 0x00, 0x04, 0x0, 0x3e },
{ 0x03, 0x00, 0x04, 0x0, 0x3c },
{ 0x03, 0x00, 0x04, 0x0, 0x3a },
{ 0x03, 0x00, 0x04, 0x0, 0x39 },
{ 0x03, 0x00, 0x04, 0x0, 0x37 },
{ 0x03, 0x00, 0x04, 0x0, 0x36 },
{ 0x03, 0x00, 0x04, 0x0, 0x34 },
{ 0x03, 0x00, 0x04, 0x0, 0x33 },
{ 0x03, 0x00, 0x04, 0x0, 0x31 },
{ 0x03, 0x00, 0x04, 0x0, 0x30 },
{ 0x03, 0x00, 0x04, 0x0, 0x2e },
{ 0x03, 0x00, 0x03, 0x0, 0x3c },
{ 0x03, 0x00, 0x03, 0x0, 0x3a },
{ 0x03, 0x00, 0x03, 0x0, 0x39 },
{ 0x03, 0x00, 0x03, 0x0, 0x37 },
{ 0x03, 0x00, 0x03, 0x0, 0x36 },
{ 0x03, 0x00, 0x03, 0x0, 0x34 },
{ 0x03, 0x00, 0x03, 0x0, 0x33 },
{ 0x03, 0x00, 0x03, 0x0, 0x31 },
{ 0x03, 0x00, 0x03, 0x0, 0x30 },
{ 0x03, 0x00, 0x03, 0x0, 0x2e },
{ 0x03, 0x00, 0x03, 0x0, 0x2d },
{ 0x03, 0x00, 0x03, 0x0, 0x2c },
{ 0x03, 0x00, 0x03, 0x0, 0x2b },
{ 0x03, 0x00, 0x03, 0x0, 0x29 },
{ 0x03, 0x00, 0x02, 0x0, 0x3d },
{ 0x03, 0x00, 0x02, 0x0, 0x3b },
{ 0x03, 0x00, 0x02, 0x0, 0x39 },
{ 0x03, 0x00, 0x02, 0x0, 0x38 },
{ 0x03, 0x00, 0x02, 0x0, 0x36 },
{ 0x03, 0x00, 0x02, 0x0, 0x35 },
{ 0x03, 0x00, 0x02, 0x0, 0x33 },
{ 0x03, 0x00, 0x02, 0x0, 0x32 },
{ 0x03, 0x00, 0x02, 0x0, 0x30 },
{ 0x03, 0x00, 0x02, 0x0, 0x2f },
{ 0x03, 0x00, 0x02, 0x0, 0x2e },
{ 0x03, 0x00, 0x02, 0x0, 0x2c },
{ 0x03, 0x00, 0x02, 0x0, 0x2b },
{ 0x03, 0x00, 0x02, 0x0, 0x2a },
{ 0x03, 0x00, 0x02, 0x0, 0x29 },
{ 0x03, 0x00, 0x02, 0x0, 0x27 },
{ 0x03, 0x00, 0x02, 0x0, 0x26 },
{ 0x03, 0x00, 0x02, 0x0, 0x25 },
{ 0x03, 0x00, 0x02, 0x0, 0x24 },
{ 0x03, 0x00, 0x02, 0x0, 0x23 },
{ 0x03, 0x00, 0x02, 0x0, 0x22 },
{ 0x03, 0x00, 0x02, 0x0, 0x21 },
{ 0x03, 0x00, 0x02, 0x0, 0x20 },
{ 0x03, 0x00, 0x01, 0x0, 0x3f },
{ 0x03, 0x00, 0x01, 0x0, 0x3d },
{ 0x03, 0x00, 0x01, 0x0, 0x3b },
{ 0x03, 0x00, 0x01, 0x0, 0x39 },
};
/**************************************************
* SW control.
**************************************************/
static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001,
};
/**************************************************
* R/W ops.
**************************************************/
u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
{
u32 type, value;
type = offset & B43_LCNTAB_TYPEMASK;
offset &= ~B43_LCNTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
switch (type) {
case B43_LCNTAB_8BIT:
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF;
break;
case B43_LCNTAB_16BIT:
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
break;
case B43_LCNTAB_32BIT:
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
break;
default:
B43_WARN_ON(1);
value = 0;
}
return value;
}
void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data)
{
u32 type;
u8 *data = _data;
unsigned int i;
type = offset & B43_LCNTAB_TYPEMASK;
offset &= ~B43_LCNTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
switch (type) {
case B43_LCNTAB_8BIT:
*data = b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATALO) & 0xFF;
data++;
break;
case B43_LCNTAB_16BIT:
*((u16 *)data) = b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATALO);
data += 2;
break;
case B43_LCNTAB_32BIT:
*((u32 *)data) = b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATALO);
*((u32 *)data) |= (b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATAHI) << 16);
data += 4;
break;
default:
B43_WARN_ON(1);
}
}
}
void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value)
{
u32 type;
type = offset & B43_LCNTAB_TYPEMASK;
offset &= 0xFFFF;
switch (type) {
case B43_LCNTAB_8BIT:
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
break;
case B43_LCNTAB_16BIT:
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
break;
case B43_LCNTAB_32BIT:
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF);
break;
default:
B43_WARN_ON(1);
}
return;
}
void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data)
{
u32 type, value;
const u8 *data = _data;
unsigned int i;
type = offset & B43_LCNTAB_TYPEMASK;
offset &= ~B43_LCNTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
switch (type) {
case B43_LCNTAB_8BIT:
value = *data;
data++;
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
break;
case B43_LCNTAB_16BIT:
value = *((u16 *)data);
data += 2;
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
break;
case B43_LCNTAB_32BIT:
value = *((u32 *)data);
data += 4;
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI,
value >> 16);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO,
value & 0xFFFF);
break;
default:
B43_WARN_ON(1);
}
}
}
/**************************************************
* Tables ops.
**************************************************/
#define lcntab_upload(dev, offset, data) do { \
b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
{
lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b);
lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c);
lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d);
lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e);
lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f);
lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10);
lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11);
lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12);
lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14);
lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17);
lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
}
static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
{
u32 i;
u32 val;
u16 pa_gain = 0x70;
if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
pa_gain = 0x10;
for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
val = ((pa_gain << 24) |
(gain_table[i].pad << 16) |
(gain_table[i].pga << 8) |
gain_table[i].gm);
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
/* brcmsmac doesn't maskset, we follow newer wl here */
val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
val &= 0x000fffff;
val |= ((gain_table[i].dac << 28) |
(gain_table[i].bb_mult << 20));
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
}
}
/* wlc_lcnphy_load_rfpower */
static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
{
u32 bbmult, rfgain;
u8 i;
for (i = 0; i < 128; i++) {
bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
bbmult >>= 20;
rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
/* TODO: calculate value for 0x240 + i table offset
* b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
*/
}
}
/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
{
int i;
u32 tmp;
for (i = 0; i < 128; i++) {
tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
}
}
/* wlc_lcnphy_clear_papd_comptable */
static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
{
u8 i;
for (i = 0; i < 0x80; i++)
b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
}
/* wlc_lcnphy_tbl_init */
void b43_phy_lcn_tables_init(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
b43_phy_lcn_upload_static_tables(dev);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if (sprom->boardflags_lo & B43_BFL_FEM)
b43_phy_lcn_load_tx_gain_tab(dev,
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
else
b43err(dev->wl,
"TX gain table unknown for this card\n");
}
if (sprom->boardflags_lo & B43_BFL_FEM &&
!(sprom->boardflags_hi & B43_BFH_FEM_BT))
b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
b43_lcntab_sw_ctl_4313_epa_rev0);
else
b43err(dev->wl, "SW ctl table is unknown for this card\n");
b43_phy_lcn_load_rfpower(dev);
b43_phy_lcn_rewrite_rfpower_table(dev);
b43_phy_lcn_clean_papd_comp_table(dev);
}

View File

@@ -0,0 +1,24 @@
#ifndef B43_TABLES_PHY_LCN_H_
#define B43_TABLES_PHY_LCN_H_
/* The LCN-PHY tables. */
#define B43_LCNTAB_TYPEMASK 0xF0000000
#define B43_LCNTAB_8BIT 0x10000000
#define B43_LCNTAB_16BIT 0x20000000
#define B43_LCNTAB_32BIT 0x30000000
#define B43_LCNTAB8(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_8BIT)
#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT)
#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT)
#define B43_LCNTAB_TX_GAIN_SIZE 128
u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_phy_lcn_tables_init(struct b43_wldev *dev);
#endif /* B43_TABLES_PHY_LCN_H_ */

View File

@@ -0,0 +1,634 @@
/*
Broadcom B43 wireless driver
PHY workarounds.
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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 "main.h"
#include "tables.h"
#include "phy_common.h"
#include "wa.h"
static void b43_wa_papd(struct b43_wldev *dev)
{
u16 backup;
backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7);
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0);
b43_dummy_transmission(dev, true, true);
b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup);
}
static void b43_wa_auxclipthr(struct b43_wldev *dev)
{
b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x3800);
}
static void b43_wa_afcdac(struct b43_wldev *dev)
{
b43_phy_write(dev, 0x0035, 0x03FF);
b43_phy_write(dev, 0x0036, 0x0400);
}
static void b43_wa_txdc_offset(struct b43_wldev *dev)
{
b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 0, 0x0051);
}
void b43_wa_initgains(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9);
b43_phy_mask(dev, B43_PHY_LPFGAINCTL, 0xFF0F);
if (phy->rev <= 2)
b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF);
b43_radio_write16(dev, 0x0002, 0x1FBF);
b43_phy_write(dev, 0x0024, 0x4680);
b43_phy_write(dev, 0x0020, 0x0003);
b43_phy_write(dev, 0x001D, 0x0F40);
b43_phy_write(dev, 0x001F, 0x1C00);
if (phy->rev <= 3)
b43_phy_maskset(dev, 0x002A, 0x00FF, 0x0400);
else if (phy->rev == 5) {
b43_phy_maskset(dev, 0x002A, 0x00FF, 0x1A00);
b43_phy_write(dev, 0x00CC, 0x2121);
}
if (phy->rev >= 3)
b43_phy_write(dev, 0x00BA, 0x3ED5);
}
static void b43_wa_divider(struct b43_wldev *dev)
{
b43_phy_mask(dev, 0x002B, ~0x0100);
b43_phy_write(dev, 0x008E, 0x58C1);
}
static void b43_wa_gt(struct b43_wldev *dev) /* Gain table. */
{
if (dev->phy.rev <= 2) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 0, 15);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 1, 31);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 2, 42);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 3, 48);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 4, 58);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 0, 3);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 1, 3);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 2, 7);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25);
}
}
static void b43_wa_rssi_lt(struct b43_wldev *dev) /* RSSI lookup table */
{
int i;
if (0 /* FIXME: For APHY.rev=2 this might be needed */) {
for (i = 0; i < 8; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i + 8);
for (i = 8; i < 16; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i - 8);
} else {
for (i = 0; i < 64; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i);
}
}
static void b43_wa_analog(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
u16 ofdmrev;
ofdmrev = b43_phy_read(dev, B43_PHY_VERSION_OFDM) & B43_PHYVER_VERSION;
if (ofdmrev > 2) {
if (phy->type == B43_PHYTYPE_A)
b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1808);
else
b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1000);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 3, 0x1044);
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 4, 0x7201);
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 6, 0x0040);
}
}
static void b43_wa_dac(struct b43_wldev *dev)
{
if (dev->phy.analog == 1)
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1,
(b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0034) | 0x0008);
else
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1,
(b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0078) | 0x0010);
}
static void b43_wa_fft(struct b43_wldev *dev) /* Fine frequency table */
{
int i;
if (dev->phy.type == B43_PHYTYPE_A)
for (i = 0; i < B43_TAB_FINEFREQA_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqa[i]);
else
for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqg[i]);
}
static void b43_wa_nft(struct b43_wldev *dev) /* Noise figure table */
{
struct b43_phy *phy = &dev->phy;
int i;
if (phy->type == B43_PHYTYPE_A) {
if (phy->rev == 2)
for (i = 0; i < B43_TAB_NOISEA2_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea2[i]);
else
for (i = 0; i < B43_TAB_NOISEA3_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea3[i]);
} else {
if (phy->rev == 1)
for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg1[i]);
else
for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg2[i]);
}
}
static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
{
int i;
for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
}
static void b43_write_null_nst(struct b43_wldev *dev)
{
int i;
for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0);
}
static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
{
int i;
for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
}
static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
{
struct b43_phy *phy = &dev->phy;
if (phy->type == B43_PHYTYPE_A) {
if (phy->rev <= 1)
b43_write_null_nst(dev);
else if (phy->rev == 2)
b43_write_nst(dev, b43_tab_noisescalea2);
else if (phy->rev == 3)
b43_write_nst(dev, b43_tab_noisescalea3);
else
b43_write_nst(dev, b43_tab_noisescaleg3);
} else {
if (phy->rev >= 6) {
if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
b43_write_nst(dev, b43_tab_noisescaleg3);
else
b43_write_nst(dev, b43_tab_noisescaleg2);
} else {
b43_write_nst(dev, b43_tab_noisescaleg1);
}
}
}
static void b43_wa_art(struct b43_wldev *dev) /* ADV retard table */
{
int i;
for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
b43_ofdmtab_write32(dev, B43_OFDMTAB_ADVRETARD,
i, b43_tab_retard[i]);
}
static void b43_wa_txlna_gain(struct b43_wldev *dev)
{
b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 13, 0x0000);
}
static void b43_wa_crs_reset(struct b43_wldev *dev)
{
b43_phy_write(dev, 0x002C, 0x0064);
}
static void b43_wa_2060txlna_gain(struct b43_wldev *dev)
{
b43_hf_write(dev, b43_hf_read(dev) |
B43_HF_2060W);
}
static void b43_wa_lms(struct b43_wldev *dev)
{
b43_phy_maskset(dev, 0x0055, 0xFFC0, 0x0004);
}
static void b43_wa_mixedsignal(struct b43_wldev *dev)
{
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1, 3);
}
static void b43_wa_msst(struct b43_wldev *dev) /* Min sigma square table */
{
struct b43_phy *phy = &dev->phy;
int i;
const u16 *tab;
if (phy->type == B43_PHYTYPE_A) {
tab = b43_tab_sigmasqr1;
} else if (phy->type == B43_PHYTYPE_G) {
tab = b43_tab_sigmasqr2;
} else {
B43_WARN_ON(1);
return;
}
for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_MINSIGSQ,
i, tab[i]);
}
}
static void b43_wa_iqadc(struct b43_wldev *dev)
{
if (dev->phy.analog == 4)
b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 0,
b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 0) & ~0xF000);
}
static void b43_wa_crs_ed(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
if (phy->rev == 1) {
b43_phy_write(dev, B43_PHY_CRSTHRES1_R1, 0x4F19);
} else if (phy->rev == 2) {
b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861);
b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271);
b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
} else {
b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098);
b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070);
b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080);
b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
}
}
static void b43_wa_crs_thr(struct b43_wldev *dev)
{
b43_phy_maskset(dev, B43_PHY_CRS0, ~0x03C0, 0xD000);
}
static void b43_wa_crs_blank(struct b43_wldev *dev)
{
b43_phy_write(dev, B43_PHY_OFDM(0x2C), 0x005A);
}
static void b43_wa_cck_shiftbits(struct b43_wldev *dev)
{
b43_phy_write(dev, B43_PHY_CCKSHIFTBITS, 0x0026);
}
static void b43_wa_wrssi_offset(struct b43_wldev *dev)
{
int i;
if (dev->phy.rev == 1) {
for (i = 0; i < 16; i++) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI_R1,
i, 0x0020);
}
} else {
for (i = 0; i < 32; i++) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI,
i, 0x0820);
}
}
}
static void b43_wa_txpuoff_rxpuon(struct b43_wldev *dev)
{
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 2, 15);
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 3, 20);
}
static void b43_wa_altagc(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
if (phy->rev == 1) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 254);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 1, 13);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 2, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 3, 25);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 0, 0x2710);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 1, 0x9B83);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 2, 0x9B83);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 3, 0x0F8D);
b43_phy_write(dev, B43_PHY_LMS, 4);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0, 254);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 1, 13);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 2, 19);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
}
b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, 0x00FF, 0x5700);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80);
b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300);
b43_radio_set(dev, 0x7A, 0x0008);
b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x000F, 0x0008);
b43_phy_maskset(dev, B43_PHY_P1P2GAIN, ~0x0F00, 0x0600);
b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x0F00, 0x0700);
b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x0F00, 0x0100);
if (phy->rev == 1) {
b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x000F, 0x0007);
}
b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x00FF, 0x001C);
b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x3F00, 0x0200);
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), ~0x00FF, 0x001C);
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020);
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200);
b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E);
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), 0x00FF, 0x1A00);
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028);
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), 0x00FF, 0x2C00);
if (phy->rev == 1) {
b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002);
} else {
b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x001E);
b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A);
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004);
if (phy->rev >= 6) {
b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, 0x0FFF, 0x3000);
}
}
b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874);
b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00);
if (phy->rev == 1) {
b43_phy_maskset(dev, B43_PHY_DIVP1P2GAIN, ~0x0F00, 0x0600);
b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E);
b43_phy_maskset(dev, B43_PHY_ANTWRSETT, ~0x00FF, 0x001E);
b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 2, 16);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 3, 28);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 0, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 1, 7);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 2, 16);
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28);
}
if (phy->rev >= 6) {
b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x0003);
b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x1000);
}
b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */
}
static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */
{
b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0x7654);
}
static void b43_wa_cpll_nonpilot(struct b43_wldev *dev)
{
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 0, 0);
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 1, 0);
}
static void b43_wa_rssi_adc(struct b43_wldev *dev)
{
if (dev->phy.analog == 4)
b43_phy_write(dev, 0x00DC, 0x7454);
}
static void b43_wa_boards_a(struct b43_wldev *dev)
{
if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
dev->dev->board_type == SSB_BOARD_BU4306 &&
dev->dev->board_rev < 0x30) {
b43_phy_write(dev, 0x0010, 0xE000);
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
} else {
if (dev->dev->board_type == SSB_BOARD_MP4318 &&
dev->dev->board_rev < 0x20) {
b43_phy_write(dev, 0x0013, 0x0210);
b43_phy_write(dev, 0x0014, 0x0840);
} else {
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
}
if (dev->phy.rev <= 4)
b43_phy_write(dev, 0x0010, 0xE000);
else
b43_phy_write(dev, 0x0010, 0x2000);
b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 1, 0x0039);
b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 7, 0x0040);
}
}
static void b43_wa_boards_g(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
dev->dev->board_type != SSB_BOARD_BU4306 ||
dev->dev->board_rev != 0x17) {
if (phy->rev < 2) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(phy->rev >= 7)) {
b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0023, 0x0000);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0000, 0x0000);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0003, 0x0002);
}
}
}
if (sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
}
}
void b43_wa_all(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
if (phy->type == B43_PHYTYPE_A) {
switch (phy->rev) {
case 2:
b43_wa_papd(dev);
b43_wa_auxclipthr(dev);
b43_wa_afcdac(dev);
b43_wa_txdc_offset(dev);
b43_wa_initgains(dev);
b43_wa_divider(dev);
b43_wa_gt(dev);
b43_wa_rssi_lt(dev);
b43_wa_analog(dev);
b43_wa_dac(dev);
b43_wa_fft(dev);
b43_wa_nft(dev);
b43_wa_rt(dev);
b43_wa_nst(dev);
b43_wa_art(dev);
b43_wa_txlna_gain(dev);
b43_wa_crs_reset(dev);
b43_wa_2060txlna_gain(dev);
b43_wa_lms(dev);
break;
case 3:
b43_wa_papd(dev);
b43_wa_mixedsignal(dev);
b43_wa_rssi_lt(dev);
b43_wa_txdc_offset(dev);
b43_wa_initgains(dev);
b43_wa_dac(dev);
b43_wa_nft(dev);
b43_wa_nst(dev);
b43_wa_msst(dev);
b43_wa_analog(dev);
b43_wa_gt(dev);
b43_wa_txpuoff_rxpuon(dev);
b43_wa_txlna_gain(dev);
break;
case 5:
b43_wa_iqadc(dev);
case 6:
b43_wa_papd(dev);
b43_wa_rssi_lt(dev);
b43_wa_txdc_offset(dev);
b43_wa_initgains(dev);
b43_wa_dac(dev);
b43_wa_nft(dev);
b43_wa_nst(dev);
b43_wa_msst(dev);
b43_wa_analog(dev);
b43_wa_gt(dev);
b43_wa_txpuoff_rxpuon(dev);
b43_wa_txlna_gain(dev);
break;
case 7:
b43_wa_iqadc(dev);
b43_wa_papd(dev);
b43_wa_rssi_lt(dev);
b43_wa_txdc_offset(dev);
b43_wa_initgains(dev);
b43_wa_dac(dev);
b43_wa_nft(dev);
b43_wa_nst(dev);
b43_wa_msst(dev);
b43_wa_analog(dev);
b43_wa_gt(dev);
b43_wa_txpuoff_rxpuon(dev);
b43_wa_txlna_gain(dev);
b43_wa_rssi_adc(dev);
default:
B43_WARN_ON(1);
}
b43_wa_boards_a(dev);
} else if (phy->type == B43_PHYTYPE_G) {
switch (phy->rev) {
case 1://XXX review rev1
b43_wa_crs_ed(dev);
b43_wa_crs_thr(dev);
b43_wa_crs_blank(dev);
b43_wa_cck_shiftbits(dev);
b43_wa_fft(dev);
b43_wa_nft(dev);
b43_wa_rt(dev);
b43_wa_nst(dev);
b43_wa_art(dev);
b43_wa_wrssi_offset(dev);
b43_wa_altagc(dev);
break;
case 2:
case 6:
case 7:
case 8:
case 9:
b43_wa_tr_ltov(dev);
b43_wa_crs_ed(dev);
b43_wa_rssi_lt(dev);
b43_wa_nft(dev);
b43_wa_nst(dev);
b43_wa_msst(dev);
b43_wa_wrssi_offset(dev);
b43_wa_altagc(dev);
b43_wa_analog(dev);
b43_wa_txpuoff_rxpuon(dev);
break;
default:
B43_WARN_ON(1);
}
b43_wa_boards_g(dev);
} else { /* No N PHY support so far, LP PHY is in phy_lp.c */
B43_WARN_ON(1);
}
b43_wa_cpll_nonpilot(dev);
}

View File

@@ -0,0 +1,7 @@
#ifndef B43_WA_H_
#define B43_WA_H_
void b43_wa_initgains(struct b43_wldev *dev);
void b43_wa_all(struct b43_wldev *dev);
#endif /* B43_WA_H_ */

View File

@@ -0,0 +1,947 @@
/*
Broadcom B43 wireless driver
Transmission (TX/RX) related functions.
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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 "xmit.h"
#include "phy_common.h"
#include "dma.h"
#include "pio.h"
static const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = {
{ B43_CCK_RATE_1MB, 0x0, 0x0 },
{ B43_CCK_RATE_2MB, 0x0, 0x1 },
{ B43_CCK_RATE_5MB, 0x0, 0x2 },
{ B43_CCK_RATE_11MB, 0x0, 0x3 },
{ B43_OFDM_RATE_6MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_BPSK },
{ B43_OFDM_RATE_9MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_BPSK },
{ B43_OFDM_RATE_12MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_QPSK },
{ B43_OFDM_RATE_18MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QPSK },
{ B43_OFDM_RATE_24MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_QAM16 },
{ B43_OFDM_RATE_36MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QAM16 },
{ B43_OFDM_RATE_48MB, B43_TXH_PHY1_CRATE_2_3, B43_TXH_PHY1_MODUL_QAM64 },
{ B43_OFDM_RATE_54MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QAM64 },
};
static const struct b43_tx_legacy_rate_phy_ctl_entry *
b43_tx_legacy_rate_phy_ctl_ent(u8 bitrate)
{
const struct b43_tx_legacy_rate_phy_ctl_entry *e;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
e = &(b43_tx_legacy_rate_phy_ctl[i]);
if (e->bitrate == bitrate)
return e;
}
B43_WARN_ON(1);
return NULL;
}
/* Extract the bitrate index out of a CCK PLCP header. */
static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
{
switch (plcp->raw[0]) {
case 0x0A:
return 0;
case 0x14:
return 1;
case 0x37:
return 2;
case 0x6E:
return 3;
}
return -1;
}
/* Extract the bitrate index out of an OFDM PLCP header. */
static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
{
/* For 2 GHz band first OFDM rate is at index 4, see main.c */
int base = ghz5 ? 0 : 4;
switch (plcp->raw[0] & 0xF) {
case 0xB:
return base + 0;
case 0xF:
return base + 1;
case 0xA:
return base + 2;
case 0xE:
return base + 3;
case 0x9:
return base + 4;
case 0xD:
return base + 5;
case 0x8:
return base + 6;
case 0xC:
return base + 7;
}
return -1;
}
u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
{
switch (bitrate) {
case B43_CCK_RATE_1MB:
return 0x0A;
case B43_CCK_RATE_2MB:
return 0x14;
case B43_CCK_RATE_5MB:
return 0x37;
case B43_CCK_RATE_11MB:
return 0x6E;
}
B43_WARN_ON(1);
return 0;
}
u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
{
switch (bitrate) {
case B43_OFDM_RATE_6MB:
return 0xB;
case B43_OFDM_RATE_9MB:
return 0xF;
case B43_OFDM_RATE_12MB:
return 0xA;
case B43_OFDM_RATE_18MB:
return 0xE;
case B43_OFDM_RATE_24MB:
return 0x9;
case B43_OFDM_RATE_36MB:
return 0xD;
case B43_OFDM_RATE_48MB:
return 0x8;
case B43_OFDM_RATE_54MB:
return 0xC;
}
B43_WARN_ON(1);
return 0;
}
void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
const u16 octets, const u8 bitrate)
{
__u8 *raw = plcp->raw;
if (b43_is_ofdm_rate(bitrate)) {
u32 d;
d = b43_plcp_get_ratecode_ofdm(bitrate);
B43_WARN_ON(octets & 0xF000);
d |= (octets << 5);
plcp->data = cpu_to_le32(d);
} else {
u32 plen;
plen = octets * 16 / bitrate;
if ((octets * 16 % bitrate) > 0) {
plen++;
if ((bitrate == B43_CCK_RATE_11MB)
&& ((octets * 8 % 11) < 4)) {
raw[1] = 0x84;
} else
raw[1] = 0x04;
} else
raw[1] = 0x04;
plcp->data |= cpu_to_le32(plen << 16);
raw[0] = b43_plcp_get_ratecode_cck(bitrate);
}
}
/* TODO: verify if needed for SSLPN or LCN */
static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
{
const struct b43_phy *phy = &dev->phy;
const struct b43_tx_legacy_rate_phy_ctl_entry *e;
u16 control = 0;
u16 bw;
if (phy->type == B43_PHYTYPE_LP)
bw = B43_TXH_PHY1_BW_20;
else /* FIXME */
bw = B43_TXH_PHY1_BW_20;
if (0) { /* FIXME: MIMO */
} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
control = bw;
} else {
control = bw;
e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
if (e) {
control |= e->coding_rate;
control |= e->modulation;
}
control |= B43_TXH_PHY1_MODE_SISO;
}
return control;
}
static u8 b43_calc_fallback_rate(u8 bitrate)
{
switch (bitrate) {
case B43_CCK_RATE_1MB:
return B43_CCK_RATE_1MB;
case B43_CCK_RATE_2MB:
return B43_CCK_RATE_1MB;
case B43_CCK_RATE_5MB:
return B43_CCK_RATE_2MB;
case B43_CCK_RATE_11MB:
return B43_CCK_RATE_5MB;
case B43_OFDM_RATE_6MB:
return B43_CCK_RATE_5MB;
case B43_OFDM_RATE_9MB:
return B43_OFDM_RATE_6MB;
case B43_OFDM_RATE_12MB:
return B43_OFDM_RATE_9MB;
case B43_OFDM_RATE_18MB:
return B43_OFDM_RATE_12MB;
case B43_OFDM_RATE_24MB:
return B43_OFDM_RATE_18MB;
case B43_OFDM_RATE_36MB:
return B43_OFDM_RATE_24MB;
case B43_OFDM_RATE_48MB:
return B43_OFDM_RATE_36MB;
case B43_OFDM_RATE_54MB:
return B43_OFDM_RATE_48MB;
}
B43_WARN_ON(1);
return 0;
}
/* Generate a TX data header. */
int b43_generate_txhdr(struct b43_wldev *dev,
u8 *_txhdr,
struct sk_buff *skb_frag,
struct ieee80211_tx_info *info,
u16 cookie)
{
const unsigned char *fragment_data = skb_frag->data;
unsigned int fragment_len = skb_frag->len;
struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
const struct b43_phy *phy = &dev->phy;
const struct ieee80211_hdr *wlhdr =
(const struct ieee80211_hdr *)fragment_data;
int use_encryption = !!info->control.hw_key;
__le16 fctl = wlhdr->frame_control;
struct ieee80211_rate *fbrate;
u8 rate, rate_fb;
int rate_ofdm, rate_fb_ofdm;
unsigned int plcp_fragment_len;
u32 mac_ctl = 0;
u16 phy_ctl = 0;
bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
phy->type == B43_PHYTYPE_N ||
phy->type == B43_PHYTYPE_HT);
u8 extra_ft = 0;
struct ieee80211_rate *txrate;
struct ieee80211_tx_rate *rates;
memset(txhdr, 0, sizeof(*txhdr));
txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
rate_ofdm = b43_is_ofdm_rate(rate);
fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
rate_fb = fbrate->hw_value;
rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
if (rate_ofdm)
txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
else
txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
txhdr->mac_frame_ctl = wlhdr->frame_control;
memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
/* Calculate duration for fallback rate */
if ((rate_fb == rate) ||
(wlhdr->duration_id & cpu_to_le16(0x8000)) ||
(wlhdr->duration_id == cpu_to_le16(0))) {
/* If the fallback rate equals the normal rate or the
* dur_id field contains an AID, CFP magic or 0,
* use the original dur_id field. */
txhdr->dur_fb = wlhdr->duration_id;
} else {
txhdr->dur_fb = ieee80211_generic_frame_duration(
dev->wl->hw, info->control.vif, info->band,
fragment_len, fbrate);
}
plcp_fragment_len = fragment_len + FCS_LEN;
if (use_encryption) {
u8 key_idx = info->control.hw_key->hw_key_idx;
struct b43_key *key;
int wlhdr_len;
size_t iv_len;
B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
key = &(dev->key[key_idx]);
if (unlikely(!key->keyconf)) {
/* This key is invalid. This might only happen
* in a short timeframe after machine resume before
* we were able to reconfigure keys.
* Drop this packet completely. Do not transmit it
* unencrypted to avoid leaking information. */
return -ENOKEY;
}
/* Hardware appends ICV. */
plcp_fragment_len += info->control.hw_key->icv_len;
key_idx = b43_kidx_to_fw(dev, key_idx);
mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
B43_TXH_MAC_KEYIDX;
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
B43_TXH_MAC_KEYALG;
wlhdr_len = ieee80211_hdrlen(fctl);
if (key->algorithm == B43_SEC_ALGO_TKIP) {
u16 phase1key[5];
int i;
/* 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_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];
txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
}
/* iv16 */
memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
} else {
iv_len = min_t(size_t, info->control.hw_key->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
}
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
plcp_fragment_len, rate);
break;
case B43_FW_HDR_351:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
plcp_fragment_len, rate);
break;
case B43_FW_HDR_410:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
plcp_fragment_len, rate);
break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
/* Extra Frame Types */
if (rate_fb_ofdm)
extra_ft |= B43_TXH_EFT_FB_OFDM;
else
extra_ft |= B43_TXH_EFT_FB_CCK;
/* Set channel radio code. Note that the micrcode ORs 0x100 to
* this value before comparing it to the value in SHM, if this
* is a 5Ghz packet.
*/
txhdr->chan_radio_code = phy->channel;
/* PHY TX Control word */
if (rate_ofdm)
phy_ctl |= B43_TXH_PHY_ENC_OFDM;
else
phy_ctl |= B43_TXH_PHY_ENC_CCK;
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
switch (b43_ieee80211_antenna_sanitize(dev, 0)) {
case 0: /* Default */
phy_ctl |= B43_TXH_PHY_ANT01AUTO;
break;
case 1: /* Antenna 0 */
phy_ctl |= B43_TXH_PHY_ANT0;
break;
case 2: /* Antenna 1 */
phy_ctl |= B43_TXH_PHY_ANT1;
break;
case 3: /* Antenna 2 */
phy_ctl |= B43_TXH_PHY_ANT2;
break;
case 4: /* Antenna 3 */
phy_ctl |= B43_TXH_PHY_ANT3;
break;
default:
B43_WARN_ON(1);
}
rates = info->control.rates;
/* MAC control */
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43_TXH_MAC_ACK;
/* use hardware sequence counter as the non-TID counter */
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
mac_ctl |= B43_TXH_MAC_HWSEQ;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43_TXH_MAC_STMSDU;
if (!phy->gmode)
mac_ctl |= B43_TXH_MAC_5GHZ;
/* Overwrite rates[0].count to make the retry calculation
* in the tx status easier. need the actual retry limit to
* detect whether the fallback rate was used.
*/
if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
mac_ctl |= B43_TXH_MAC_LONGFRAME;
} else {
rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
}
/* Generate the RTS or CTS-to-self frame */
if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
struct ieee80211_hdr *uninitialized_var(hdr);
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
struct b43_plcp_hdr6 *uninitialized_var(plcp);
struct ieee80211_rate *rts_cts_rate;
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
rts_rate_fb = b43_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
struct ieee80211_cts *uninitialized_var(cts);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
cts = (struct ieee80211_cts *)
(txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
cts = (struct ieee80211_cts *)
(txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
cts = (struct ieee80211_cts *)
(txhdr->format_410.rts_frame);
break;
}
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
info, cts);
mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
struct ieee80211_rts *uninitialized_var(rts);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
rts = (struct ieee80211_rts *)
(txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
rts = (struct ieee80211_rts *)
(txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
rts = (struct ieee80211_rts *)
(txhdr->format_410.rts_frame);
break;
}
ieee80211_rts_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
info, rts);
mac_ctl |= B43_TXH_MAC_SENDRTS;
len = sizeof(struct ieee80211_rts);
}
len += FCS_LEN;
/* Generate the PLCP headers for the RTS/CTS frame */
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
plcp = &txhdr->format_598.rts_plcp;
break;
case B43_FW_HDR_351:
plcp = &txhdr->format_351.rts_plcp;
break;
case B43_FW_HDR_410:
plcp = &txhdr->format_410.rts_plcp;
break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate);
plcp = &txhdr->rts_plcp_fb;
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate_fb);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
hdr = (struct ieee80211_hdr *)
(&txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
hdr = (struct ieee80211_hdr *)
(&txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
hdr = (struct ieee80211_hdr *)
(&txhdr->format_410.rts_frame);
break;
}
txhdr->rts_dur_fb = hdr->duration_id;
if (rts_rate_ofdm) {
extra_ft |= B43_TXH_EFT_RTS_OFDM;
txhdr->phy_rate_rts =
b43_plcp_get_ratecode_ofdm(rts_rate);
} else {
extra_ft |= B43_TXH_EFT_RTS_CCK;
txhdr->phy_rate_rts =
b43_plcp_get_ratecode_cck(rts_rate);
}
if (rts_rate_fb_ofdm)
extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
else
extra_ft |= B43_TXH_EFT_RTSFB_CCK;
if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
fill_phy_ctl1) {
txhdr->phy_ctl1_rts = cpu_to_le16(
b43_generate_tx_phy_ctl1(dev, rts_rate));
txhdr->phy_ctl1_rts_fb = cpu_to_le16(
b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
}
}
/* Magic cookie */
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
txhdr->format_598.cookie = cpu_to_le16(cookie);
break;
case B43_FW_HDR_351:
txhdr->format_351.cookie = cpu_to_le16(cookie);
break;
case B43_FW_HDR_410:
txhdr->format_410.cookie = cpu_to_le16(cookie);
break;
}
if (fill_phy_ctl1) {
txhdr->phy_ctl1 =
cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
txhdr->phy_ctl1_fb =
cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
}
/* Apply the bitfields */
txhdr->mac_ctl = cpu_to_le32(mac_ctl);
txhdr->phy_ctl = cpu_to_le16(phy_ctl);
txhdr->extra_ft = extra_ft;
return 0;
}
static s8 b43_rssi_postprocess(struct b43_wldev *dev,
u8 in_rssi, int ofdm,
int adjust_2053, int adjust_2050)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
s32 tmp;
switch (phy->radio_ver) {
case 0x2050:
if (ofdm) {
tmp = in_rssi;
if (tmp > 127)
tmp -= 256;
tmp *= 73;
tmp /= 64;
if (adjust_2050)
tmp += 25;
else
tmp -= 3;
} else {
if (dev->dev->bus_sprom->
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
tmp = gphy->nrssi_lt[in_rssi];
tmp = 31 - tmp;
tmp *= -131;
tmp /= 128;
tmp -= 57;
} else {
tmp = in_rssi;
tmp = 31 - tmp;
tmp *= -149;
tmp /= 128;
tmp -= 68;
}
if (phy->type == B43_PHYTYPE_G && adjust_2050)
tmp += 25;
}
break;
case 0x2060:
if (in_rssi > 127)
tmp = in_rssi - 256;
else
tmp = in_rssi;
break;
default:
tmp = in_rssi;
tmp -= 11;
tmp *= 103;
tmp /= 64;
if (adjust_2053)
tmp -= 109;
else
tmp -= 83;
}
return (s8) tmp;
}
//TODO
#if 0
static s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
{
struct b43_phy *phy = &dev->phy;
s8 ret;
if (phy->type == B43_PHYTYPE_A) {
//TODO: Incomplete specs.
ret = 0;
} else
ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
return ret;
}
#endif
void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
{
struct ieee80211_rx_status status;
struct b43_plcp_hdr6 *plcp;
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
__le16 fctl;
u16 phystat0, phystat3;
u16 uninitialized_var(chanstat), uninitialized_var(mactime);
u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
int padding, rate_idx;
memset(&status, 0, sizeof(status));
/* Get metadata about the frame from the header. */
phystat0 = le16_to_cpu(rxhdr->phy_status0);
phystat3 = le16_to_cpu(rxhdr->phy_status3);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
macstat = le32_to_cpu(rxhdr->format_598.mac_status);
mactime = le16_to_cpu(rxhdr->format_598.mac_time);
chanstat = le16_to_cpu(rxhdr->format_598.channel);
break;
case B43_FW_HDR_410:
case B43_FW_HDR_351:
macstat = le32_to_cpu(rxhdr->format_351.mac_status);
mactime = le16_to_cpu(rxhdr->format_351.mac_time);
chanstat = le16_to_cpu(rxhdr->format_351.channel);
break;
}
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
dev->wl->ieee_stats.dot11FCSErrorCount++;
status.flag |= RX_FLAG_FAILED_FCS_CRC;
}
if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
status.flag |= RX_FLAG_FAILED_PLCP_CRC;
if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
status.flag |= RX_FLAG_SHORTPRE;
if (macstat & B43_RX_MAC_DECERR) {
/* Decryption with the given key failed.
* Drop the packet. We also won't be able to decrypt it with
* the key in software. */
goto drop;
}
/* Skip PLCP and padding */
padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
goto drop;
}
plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
/* The skb contains the Wireless Header + payload data now */
if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) {
b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
goto drop;
}
wlhdr = (struct ieee80211_hdr *)(skb->data);
fctl = wlhdr->frame_control;
if (macstat & B43_RX_MAC_DEC) {
unsigned int keyidx;
int wlhdr_len;
keyidx = ((macstat & B43_RX_MAC_KEYIDX)
>> B43_RX_MAC_KEYIDX_SHIFT);
/* We must adjust the key index here. We want the "physical"
* key index, but the ucode passed it slightly different.
*/
keyidx = b43_kidx_to_raw(dev, keyidx);
B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
wlhdr_len = ieee80211_hdrlen(fctl);
if (unlikely(skb->len < (wlhdr_len + 3))) {
b43dbg(dev->wl,
"RX: Packet size underrun (3)\n");
goto drop;
}
status.flag |= RX_FLAG_DECRYPTED;
}
}
/* Link quality statistics */
switch (chanstat & B43_RX_CHAN_PHYTYPE) {
case B43_PHYTYPE_HT:
/* TODO: is max the right choice? */
status.signal = max_t(__s8,
max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
rxhdr->phy_ht_power2);
break;
case B43_PHYTYPE_N:
/* Broadcom has code for min and avg, but always uses max */
if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
status.signal = max(rxhdr->power1, rxhdr->power2);
else
status.signal = max(rxhdr->power0, rxhdr->power1);
break;
case B43_PHYTYPE_A:
case B43_PHYTYPE_B:
case B43_PHYTYPE_G:
case B43_PHYTYPE_LP:
status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE));
break;
}
if (phystat0 & B43_RX_PHYST0_OFDM)
rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
!!(chanstat & B43_RX_CHAN_5GHZ));
else
rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
if (unlikely(rate_idx == -1)) {
/* PLCP seems to be corrupted.
* Drop the frame, if we are not interested in corrupted frames. */
if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
goto drop;
}
status.rate_idx = rate_idx;
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
/*
* All frames on monitor interfaces and beacons always need a full
* 64-bit timestamp. Monitor interfaces need it for diagnostic
* purposes and beacons for IBSS merging.
* This code assumes we get to process the packet within 16 bits
* of timestamp, i.e. about 65 milliseconds after the PHY received
* the first symbol.
*/
if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
u16 low_mactime_now;
b43_tsf_read(dev, &status.mactime);
low_mactime_now = status.mactime;
status.mactime = status.mactime & ~0xFFFFULL;
status.mactime += mactime;
if (low_mactime_now <= mactime)
status.mactime -= 0x10000;
status.flag |= RX_FLAG_MACTIME_START;
}
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
switch (chanstat & B43_RX_CHAN_PHYTYPE) {
case B43_PHYTYPE_A:
status.band = IEEE80211_BAND_5GHZ;
B43_WARN_ON(1);
/* FIXME: We don't really know which value the "chanid" contains.
* So the following assignment might be wrong. */
status.freq =
ieee80211_channel_to_frequency(chanid, status.band);
break;
case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ;
/* Somewhere between 478.104 and 508.1084 firmware for G-PHY
* has been modified to be compatible with N-PHY and others.
*/
if (dev->fw.rev >= 508)
status.freq = ieee80211_channel_to_frequency(chanid, status.band);
else
status.freq = chanid + 2400;
break;
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT:
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ)
status.band = IEEE80211_BAND_5GHZ;
else
status.band = IEEE80211_BAND_2GHZ;
status.freq =
ieee80211_channel_to_frequency(chanid, status.band);
break;
default:
B43_WARN_ON(1);
goto drop;
}
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx_ni(dev->wl->hw, skb);
#if B43_DEBUG
dev->rx_count++;
#endif
return;
drop:
dev_kfree_skb_any(skb);
}
void b43_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
b43_debugfs_log_txstat(dev, status);
if (status->intermediate)
return;
if (status->for_ampdu)
return;
if (!status->acked)
dev->wl->ieee_stats.dot11ACKFailureCount++;
if (status->rts_count) {
if (status->rts_count == 0xF) //FIXME
dev->wl->ieee_stats.dot11RTSFailureCount++;
else
dev->wl->ieee_stats.dot11RTSSuccessCount++;
}
if (b43_using_pio_transfers(dev))
b43_pio_handle_txstatus(dev, status);
else
b43_dma_handle_txstatus(dev, status);
b43_phy_txpower_check(dev, 0);
}
/* Fill out the mac80211 TXstatus report based on the b43-specific
* txstatus report data. This returns a boolean whether the frame was
* successfully transmitted. */
bool b43_fill_txstatus_report(struct b43_wldev *dev,
struct ieee80211_tx_info *report,
const struct b43_txstatus *status)
{
bool frame_success = true;
int retry_limit;
/* preserve the confiured retry limit before clearing the status
* The xmit function has overwritten the rc's value with the actual
* retry limit done by the hardware */
retry_limit = report->status.rates[0].count;
ieee80211_tx_info_clear_status(report);
if (status->acked) {
/* The frame was ACKed. */
report->flags |= IEEE80211_TX_STAT_ACK;
} else {
/* The frame was not ACKed... */
if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
/* ...but we expected an ACK. */
frame_success = false;
}
}
if (status->frame_count == 0) {
/* The frame was not transmitted at all. */
report->status.rates[0].count = 0;
} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
/*
* If the short retries (RTS, not data frame) have exceeded
* the limit, the hw will not have tried the selected rate,
* but will have used the fallback rate instead.
* Don't let the rate control count attempts for the selected
* rate in this case, otherwise the statistics will be off.
*/
report->status.rates[0].count = 0;
report->status.rates[1].count = status->frame_count;
} else {
if (status->frame_count > retry_limit) {
report->status.rates[0].count = retry_limit;
report->status.rates[1].count = status->frame_count -
retry_limit;
} else {
report->status.rates[0].count = status->frame_count;
report->status.rates[1].idx = -1;
}
}
return frame_success;
}
/* Stop any TX operation on the device (suspend the hardware queues) */
void b43_tx_suspend(struct b43_wldev *dev)
{
if (b43_using_pio_transfers(dev))
b43_pio_tx_suspend(dev);
else
b43_dma_tx_suspend(dev);
}
/* Resume any TX operation on the device (resume the hardware queues) */
void b43_tx_resume(struct b43_wldev *dev)
{
if (b43_using_pio_transfers(dev))
b43_pio_tx_resume(dev);
else
b43_dma_tx_resume(dev);
}

View File

@@ -0,0 +1,416 @@
#ifndef B43_XMIT_H_
#define B43_XMIT_H_
#include "main.h"
#include <net/mac80211.h>
#define _b43_declare_plcp_hdr(size) \
struct b43_plcp_hdr##size { \
union { \
__le32 data; \
__u8 raw[size]; \
} __packed; \
} __packed
/* struct b43_plcp_hdr4 */
_b43_declare_plcp_hdr(4);
/* struct b43_plcp_hdr6 */
_b43_declare_plcp_hdr(6);
#undef _b43_declare_plcp_hdr
/* TX header for v4 firmware */
struct b43_txhdr {
__le32 mac_ctl; /* MAC TX control */
__le16 mac_frame_ctl; /* Copy of the FrameControl field */
__le16 tx_fes_time_norm; /* TX FES Time Normal */
__le16 phy_ctl; /* PHY TX control */
__le16 phy_ctl1; /* PHY TX control word 1 */
__le16 phy_ctl1_fb; /* PHY TX control word 1 for fallback rates */
__le16 phy_ctl1_rts; /* PHY TX control word 1 RTS */
__le16 phy_ctl1_rts_fb; /* PHY TX control word 1 RTS for fallback rates */
__u8 phy_rate; /* PHY rate */
__u8 phy_rate_rts; /* PHY rate for RTS/CTS */
__u8 extra_ft; /* Extra Frame Types */
__u8 chan_radio_code; /* Channel Radio Code */
__u8 iv[16]; /* Encryption IV */
__u8 tx_receiver[6]; /* TX Frame Receiver address */
__le16 tx_fes_time_fb; /* TX FES Time Fallback */
struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP header */
__le16 rts_dur_fb; /* RTS fallback duration */
struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP header */
__le16 dur_fb; /* Fallback duration */
__le16 mimo_modelen; /* MIMO mode length */
__le16 mimo_ratelen_fb; /* MIMO fallback rate length */
__le32 timeout; /* Timeout */
union {
/* Tested with 598.314, 644.1001 and 666.2 */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
__le16 tx_status; /* TX status */
__le16 max_n_mpdus;
__le16 max_a_bytes_mrt;
__le16 max_a_bytes_fbr;
__le16 min_m_bytes;
struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} format_598 __packed;
/* Tested with 410.2160, 478.104 and 508.* */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
__le16 tx_status; /* TX status */
struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} format_410 __packed;
/* Tested with 351.126 */
struct {
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
__le16 tx_status; /* TX status */
struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} format_351 __packed;
} __packed;
} __packed;
struct b43_tx_legacy_rate_phy_ctl_entry {
u8 bitrate;
u16 coding_rate;
u16 modulation;
};
/* MAC TX control */
#define B43_TXH_MAC_RTS_FB_SHORTPRMBL 0x80000000 /* RTS fallback preamble */
#define B43_TXH_MAC_RTS_SHORTPRMBL 0x40000000 /* RTS main rate preamble */
#define B43_TXH_MAC_FB_SHORTPRMBL 0x20000000 /* Main fallback preamble */
#define B43_TXH_MAC_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */
#define B43_TXH_MAC_KEYIDX 0x0FF00000 /* Security key index */
#define B43_TXH_MAC_KEYIDX_SHIFT 20
#define B43_TXH_MAC_ALT_TXPWR 0x00080000 /* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
#define B43_TXH_MAC_KEYALG 0x00070000 /* Security key algorithm */
#define B43_TXH_MAC_KEYALG_SHIFT 16
#define B43_TXH_MAC_AMIC 0x00008000 /* AMIC */
#define B43_TXH_MAC_RIFS 0x00004000 /* Use RIFS */
#define B43_TXH_MAC_LIFETIME 0x00002000 /* Lifetime */
#define B43_TXH_MAC_FRAMEBURST 0x00001000 /* Frameburst */
#define B43_TXH_MAC_SENDCTS 0x00000800 /* Send CTS-to-self */
#define B43_TXH_MAC_AMPDU 0x00000600 /* AMPDU status */
#define B43_TXH_MAC_AMPDU_MPDU 0x00000000 /* Regular MPDU, not an AMPDU */
#define B43_TXH_MAC_AMPDU_FIRST 0x00000200 /* First MPDU or AMPDU */
#define B43_TXH_MAC_AMPDU_INTER 0x00000400 /* Intermediate MPDU or AMPDU */
#define B43_TXH_MAC_AMPDU_LAST 0x00000600 /* Last (or only) MPDU of AMPDU */
#define B43_TXH_MAC_40MHZ 0x00000100 /* Use 40 MHz bandwidth */
#define B43_TXH_MAC_5GHZ 0x00000080 /* 5GHz band */
#define B43_TXH_MAC_DFCS 0x00000040 /* DFCS */
#define B43_TXH_MAC_IGNPMQ 0x00000020 /* Ignore PMQ */
#define B43_TXH_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */
#define B43_TXH_MAC_STMSDU 0x00000008 /* Start MSDU */
#define B43_TXH_MAC_SENDRTS 0x00000004 /* Send RTS */
#define B43_TXH_MAC_LONGFRAME 0x00000002 /* Long frame */
#define B43_TXH_MAC_ACK 0x00000001 /* Immediate ACK */
/* Extra Frame Types */
#define B43_TXH_EFT_FB 0x03 /* Data frame fallback encoding */
#define B43_TXH_EFT_FB_CCK 0x00 /* CCK */
#define B43_TXH_EFT_FB_OFDM 0x01 /* OFDM */
#define B43_TXH_EFT_FB_HT 0x02 /* HT */
#define B43_TXH_EFT_FB_VHT 0x03 /* VHT */
#define B43_TXH_EFT_RTS 0x0C /* RTS/CTS encoding */
#define B43_TXH_EFT_RTS_CCK 0x00 /* CCK */
#define B43_TXH_EFT_RTS_OFDM 0x04 /* OFDM */
#define B43_TXH_EFT_RTS_HT 0x08 /* HT */
#define B43_TXH_EFT_RTS_VHT 0x0C /* VHT */
#define B43_TXH_EFT_RTSFB 0x30 /* RTS/CTS fallback encoding */
#define B43_TXH_EFT_RTSFB_CCK 0x00 /* CCK */
#define B43_TXH_EFT_RTSFB_OFDM 0x10 /* OFDM */
#define B43_TXH_EFT_RTSFB_HT 0x20 /* HT */
#define B43_TXH_EFT_RTSFB_VHT 0x30 /* VHT */
/* PHY TX control word */
#define B43_TXH_PHY_ENC 0x0003 /* Data frame encoding */
#define B43_TXH_PHY_ENC_CCK 0x0000 /* CCK */
#define B43_TXH_PHY_ENC_OFDM 0x0001 /* OFDM */
#define B43_TXH_PHY_ENC_HT 0x0002 /* HT */
#define B43_TXH_PHY_ENC_VHT 0x0003 /* VHT */
#define B43_TXH_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
#define B43_TXH_PHY_ANT 0x03C0 /* Antenna selection */
#define B43_TXH_PHY_ANT0 0x0000 /* Use antenna 0 */
#define B43_TXH_PHY_ANT1 0x0040 /* Use antenna 1 */
#define B43_TXH_PHY_ANT01AUTO 0x00C0 /* Use antenna 0/1 auto */
#define B43_TXH_PHY_ANT2 0x0100 /* Use antenna 2 */
#define B43_TXH_PHY_ANT3 0x0200 /* Use antenna 3 */
#define B43_TXH_PHY_TXPWR 0xFC00 /* TX power */
#define B43_TXH_PHY_TXPWR_SHIFT 10
/* PHY TX control word 1 */
#define B43_TXH_PHY1_BW 0x0007 /* Bandwidth */
#define B43_TXH_PHY1_BW_10 0x0000 /* 10 MHz */
#define B43_TXH_PHY1_BW_10U 0x0001 /* 10 MHz upper */
#define B43_TXH_PHY1_BW_20 0x0002 /* 20 MHz */
#define B43_TXH_PHY1_BW_20U 0x0003 /* 20 MHz upper */
#define B43_TXH_PHY1_BW_40 0x0004 /* 40 MHz */
#define B43_TXH_PHY1_BW_40DUP 0x0005 /* 40 MHz duplicate */
#define B43_TXH_PHY1_MODE 0x0038 /* Mode */
#define B43_TXH_PHY1_MODE_SISO 0x0000 /* SISO */
#define B43_TXH_PHY1_MODE_CDD 0x0008 /* CDD */
#define B43_TXH_PHY1_MODE_STBC 0x0010 /* STBC */
#define B43_TXH_PHY1_MODE_SDM 0x0018 /* SDM */
#define B43_TXH_PHY1_CRATE 0x0700 /* Coding rate */
#define B43_TXH_PHY1_CRATE_1_2 0x0000 /* 1/2 */
#define B43_TXH_PHY1_CRATE_2_3 0x0100 /* 2/3 */
#define B43_TXH_PHY1_CRATE_3_4 0x0200 /* 3/4 */
#define B43_TXH_PHY1_CRATE_4_5 0x0300 /* 4/5 */
#define B43_TXH_PHY1_CRATE_5_6 0x0400 /* 5/6 */
#define B43_TXH_PHY1_CRATE_7_8 0x0600 /* 7/8 */
#define B43_TXH_PHY1_MODUL 0x3800 /* Modulation scheme */
#define B43_TXH_PHY1_MODUL_BPSK 0x0000 /* BPSK */
#define B43_TXH_PHY1_MODUL_QPSK 0x0800 /* QPSK */
#define B43_TXH_PHY1_MODUL_QAM16 0x1000 /* QAM16 */
#define B43_TXH_PHY1_MODUL_QAM64 0x1800 /* QAM64 */
#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
static inline
size_t b43_txhdr_size(struct b43_wldev *dev)
{
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
return 112 + sizeof(struct b43_plcp_hdr6);
case B43_FW_HDR_410:
return 104 + sizeof(struct b43_plcp_hdr6);
case B43_FW_HDR_351:
return 100 + sizeof(struct b43_plcp_hdr6);
}
return 0;
}
int b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr,
struct sk_buff *skb_frag,
struct ieee80211_tx_info *txctl, u16 cookie);
/* Transmit Status */
struct b43_txstatus {
u16 cookie; /* The cookie from the txhdr */
u16 seq; /* Sequence number */
u8 phy_stat; /* PHY TX status */
u8 frame_count; /* Frame transmit count */
u8 rts_count; /* RTS transmit count */
u8 supp_reason; /* Suppression reason */
/* flags */
u8 pm_indicated; /* PM mode indicated to AP */
u8 intermediate; /* Intermediate status notification (not final) */
u8 for_ampdu; /* Status is for an AMPDU (afterburner) */
u8 acked; /* Wireless ACK received */
};
/* txstatus supp_reason values */
enum {
B43_TXST_SUPP_NONE, /* Not suppressed */
B43_TXST_SUPP_PMQ, /* Suppressed due to PMQ entry */
B43_TXST_SUPP_FLUSH, /* Suppressed due to flush request */
B43_TXST_SUPP_PREV, /* Previous fragment failed */
B43_TXST_SUPP_CHAN, /* Channel mismatch */
B43_TXST_SUPP_LIFE, /* Lifetime expired */
B43_TXST_SUPP_UNDER, /* Buffer underflow */
B43_TXST_SUPP_ABNACK, /* Afterburner NACK */
};
/* Receive header for v4 firmware. */
struct b43_rxhdr_fw4 {
__le16 frame_len; /* Frame length */
PAD_BYTES(2);
__le16 phy_status0; /* PHY RX Status 0 */
union {
/* RSSI for A/B/G-PHYs */
struct {
__u8 jssi; /* PHY RX Status 1: JSSI */
__u8 sig_qual; /* PHY RX Status 1: Signal Quality */
} __packed;
/* RSSI for N-PHYs */
struct {
__s8 power0; /* PHY RX Status 1: Power 0 */
__s8 power1; /* PHY RX Status 1: Power 1 */
} __packed;
} __packed;
union {
/* HT-PHY */
struct {
PAD_BYTES(1);
__s8 phy_ht_power0;
} __packed;
/* RSSI for N-PHYs */
struct {
__s8 power2;
PAD_BYTES(1);
} __packed;
__le16 phy_status2; /* PHY RX Status 2 */
} __packed;
union {
/* HT-PHY */
struct {
__s8 phy_ht_power1;
__s8 phy_ht_power2;
} __packed;
__le16 phy_status3; /* PHY RX Status 3 */
} __packed;
union {
/* Tested with 598.314, 644.1001 and 666.2 */
struct {
__le16 phy_status4; /* PHY RX Status 4 */
__le16 phy_status5; /* PHY RX Status 5 */
__le32 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
} format_598 __packed;
/* Tested with 351.126, 410.2160, 478.104 and 508.* */
struct {
__le32 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
} format_351 __packed;
} __packed;
} __packed;
/* PHY RX Status 0 */
#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */
#define B43_RX_PHYST0_PLCPHCF 0x0200
#define B43_RX_PHYST0_PLCPFV 0x0100
#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */
#define B43_RX_PHYST0_LCRS 0x0040
#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */
#define B43_RX_PHYST0_UNSRATE 0x0010
#define B43_RX_PHYST0_CLIP 0x000C
#define B43_RX_PHYST0_CLIP_SHIFT 2
#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */
#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */
#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */
#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */
#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */
/* PHY RX Status 2 */
#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */
#define B43_RX_PHYST2_LNAG_SHIFT 14
#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */
#define B43_RX_PHYST2_PNAG_SHIFT 10
#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */
/* PHY RX Status 3 */
#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */
#define B43_RX_PHYST3_DIGG_SHIFT 11
#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */
/* MAC RX Status */
#define B43_RX_MAC_RXST_VALID 0x01000000 /* PHY RXST valid */
#define B43_RX_MAC_TKIP_MICERR 0x00100000 /* TKIP MIC error */
#define B43_RX_MAC_TKIP_MICATT 0x00080000 /* TKIP MIC attempted */
#define B43_RX_MAC_AGGTYPE 0x00060000 /* Aggregation type */
#define B43_RX_MAC_AGGTYPE_SHIFT 17
#define B43_RX_MAC_AMSDU 0x00010000 /* A-MSDU mask */
#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon sent flag */
#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */
#define B43_RX_MAC_KEYIDX_SHIFT 5
#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */
#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */
#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */
#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */
#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */
/* RX channel */
#define B43_RX_CHAN_40MHZ 0x1000 /* 40 Mhz channel width */
#define B43_RX_CHAN_5GHZ 0x0800 /* 5 Ghz band */
#define B43_RX_CHAN_ID 0x07F8 /* Channel ID */
#define B43_RX_CHAN_ID_SHIFT 3
#define B43_RX_CHAN_PHYTYPE 0x0007 /* PHY type */
u8 b43_plcp_get_ratecode_cck(const u8 bitrate);
u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate);
void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
const u16 octets, const u8 bitrate);
void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
void b43_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
bool b43_fill_txstatus_report(struct b43_wldev *dev,
struct ieee80211_tx_info *report,
const struct b43_txstatus *status);
void b43_tx_suspend(struct b43_wldev *dev);
void b43_tx_resume(struct b43_wldev *dev);
/* Helper functions for converting the key-table index from "firmware-format"
* to "raw-format" and back. The firmware API changed for this at some revision.
* We need to account for that here. */
static inline int b43_new_kidx_api(struct b43_wldev *dev)
{
/* FIXME: Not sure the change was at rev 351 */
return (dev->fw.rev >= 351);
}
static inline u8 b43_kidx_to_fw(struct b43_wldev *dev, u8 raw_kidx)
{
u8 firmware_kidx;
if (b43_new_kidx_api(dev)) {
firmware_kidx = raw_kidx;
} else {
if (raw_kidx >= 4) /* Is per STA key? */
firmware_kidx = raw_kidx - 4;
else
firmware_kidx = raw_kidx; /* TX default key */
}
return firmware_kidx;
}
static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx)
{
u8 raw_kidx;
if (b43_new_kidx_api(dev))
raw_kidx = firmware_kidx;
else
raw_kidx = firmware_kidx + 4; /* RX default keys or per STA keys */
return raw_kidx;
}
/* struct b43_private_tx_info - TX info private to b43.
* The structure is placed in (struct ieee80211_tx_info *)->rate_driver_data
*
* @bouncebuffer: DMA Bouncebuffer (if used)
*/
struct b43_private_tx_info {
void *bouncebuffer;
};
static inline struct b43_private_tx_info *
b43_get_priv_tx_info(struct ieee80211_tx_info *info)
{
BUILD_BUG_ON(sizeof(struct b43_private_tx_info) >
sizeof(info->rate_driver_data));
return (struct b43_private_tx_info *)info->rate_driver_data;
}
#endif /* B43_XMIT_H_ */