Commit ef1a628d authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

b43: Implement dynamic PHY API

This patch implements a dynamic "ops" based PHY API.
This is needed in order to conveniently support future PHY types
to avoid the "switch"-hell.

This patch does not change any functionality. It just moves lots
of code from one place to another and adjusts it for the changed
data structures.
Signed-off-by: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 35e032d8
b43-y += main.o b43-y += main.o
b43-y += tables.o b43-y += tables.o
b43-$(CONFIG_B43_NPHY) += tables_nphy.o b43-$(CONFIG_B43_NPHY) += tables_nphy.o
b43-y += phy.o b43-y += phy_common.o
b43-y += phy_g.o
b43-y += phy_a.o
b43-$(CONFIG_B43_NPHY) += nphy.o b43-$(CONFIG_B43_NPHY) += nphy.o
b43-y += sysfs.o b43-y += sysfs.o
b43-y += xmit.o b43-y += xmit.o
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "leds.h" #include "leds.h"
#include "rfkill.h" #include "rfkill.h"
#include "lo.h" #include "lo.h"
#include "phy.h" #include "phy_common.h"
/* The unique identifier of the firmware that's officially supported by /* The unique identifier of the firmware that's officially supported by
...@@ -508,122 +508,6 @@ struct b43_iv { ...@@ -508,122 +508,6 @@ struct b43_iv {
} __attribute__((__packed__)); } __attribute__((__packed__));
struct b43_phy {
/* Band support flags. */
bool supports_2ghz;
bool supports_5ghz;
/* GMODE bit enabled? */
bool gmode;
/* Analog Type */
u8 analog;
/* B43_PHYTYPE_ */
u8 type;
/* PHY revision number. */
u8 rev;
/* Radio versioning */
u16 radio_manuf; /* Radio manufacturer */
u16 radio_ver; /* Radio version */
u8 radio_rev; /* Radio revision */
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
/* 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];
/* TSSI to dBm table in use */
const s8 *tssi2dbm;
/* Target idle TSSI */
int tgt_idle_tssi;
/* Current idle TSSI */
int cur_idle_tssi;
/* 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 */
/* Desired TX power level (in dBm).
* This is set by the user and adjusted in b43_phy_xmitpower(). */
u8 power_level;
/* A-PHY TX Power control value. */
u16 txpwr_offset;
/* Current TX power level attenuation control values */
struct b43_bbatt bbatt;
struct b43_rfatt rfatt;
u8 tx_control; /* B43_TXCTL_XXX */
/* Hardware Power Control enabled? */
bool hardware_power_control;
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
* Each value in the stack is layed 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];
/* current channel */
u8 channel;
u16 lofcal;
u16 initval; //FIXME rename?
/* PHY TX errors counter. */
atomic_t txerr_cnt;
/* 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;
#if B43_DEBUG
/* Manual TX-power control enabled? */
bool manual_txpower_control;
/* PHY registers locked by b43_phy_lock()? */
bool phy_locked;
#endif /* B43_DEBUG */
};
/* Data structures for DMA transmission, per 80211 core. */ /* Data structures for DMA transmission, per 80211 core. */
struct b43_dma { struct b43_dma {
struct b43_dmaring *tx_ring_AC_BK; /* Background */ struct b43_dmaring *tx_ring_AC_BK; /* Background */
...@@ -908,6 +792,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type) ...@@ -908,6 +792,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
return (wl->operating && wl->if_type == type); return (wl->operating && wl->if_type == type);
} }
/**
* b43_current_band - Returns the currently used band.
* Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ.
*/
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
{
return wl->hw->conf.channel->band;
}
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
{ {
return ssb_read16(dev->dev, offset); return ssb_read16(dev->dev, offset);
......
...@@ -443,76 +443,6 @@ static ssize_t txstat_read_file(struct b43_wldev *dev, ...@@ -443,76 +443,6 @@ static ssize_t txstat_read_file(struct b43_wldev *dev,
return count; return count;
} }
static ssize_t txpower_g_read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
if (dev->phy.type != B43_PHYTYPE_G) {
fappend("Device is not a G-PHY\n");
goto out;
}
fappend("Control: %s\n", dev->phy.manual_txpower_control ?
"MANUAL" : "AUTOMATIC");
fappend("Baseband attenuation: %u\n", dev->phy.bbatt.att);
fappend("Radio attenuation: %u\n", dev->phy.rfatt.att);
fappend("TX Mixer Gain: %s\n",
(dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF");
fappend("PA Gain 2dB: %s\n",
(dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF");
fappend("PA Gain 3dB: %s\n",
(dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF");
fappend("\n\n");
fappend("You can write to this file:\n");
fappend("Writing \"auto\" enables automatic txpower control.\n");
fappend
("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" "
"enables manual txpower control.\n");
fappend("Example: 5 4 0 0 1\n");
fappend("Enables manual control with Baseband attenuation 5, "
"Radio attenuation 4, No TX Mixer Gain, "
"No PA Gain 2dB, With PA Gain 3dB.\n");
out:
return count;
}
static int txpower_g_write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
if (dev->phy.type != B43_PHYTYPE_G)
return -ENODEV;
if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) {
/* Automatic control */
dev->phy.manual_txpower_control = 0;
b43_phy_xmitpower(dev);
} else {
int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0;
/* Manual control */
if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt,
&txmix, &pa2db, &pa3db) != 5)
return -EINVAL;
b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
dev->phy.manual_txpower_control = 1;
dev->phy.bbatt.att = bbatt;
dev->phy.rfatt.att = rfatt;
dev->phy.tx_control = 0;
if (txmix)
dev->phy.tx_control |= B43_TXCTL_TXMIX;
if (pa2db)
dev->phy.tx_control |= B43_TXCTL_PA2DB;
if (pa3db)
dev->phy.tx_control |= B43_TXCTL_PA3DB;
b43_phy_lock(dev);
b43_radio_lock(dev);
b43_set_txpower_g(dev, &dev->phy.bbatt,
&dev->phy.rfatt, dev->phy.tx_control);
b43_radio_unlock(dev);
b43_phy_unlock(dev);
}
return 0;
}
/* wl->irq_lock is locked */ /* wl->irq_lock is locked */
static int restart_write_file(struct b43_wldev *dev, static int restart_write_file(struct b43_wldev *dev,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, ...@@ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
err = -ENODEV; err = -ENODEV;
goto out; goto out;
} }
lo = phy->lo_control; lo = phy->g->lo_control;
fappend("-- Local Oscillator calibration data --\n\n"); fappend("-- Local Oscillator calibration data --\n\n");
fappend("HW-power-control enabled: %d\n", fappend("HW-power-control enabled: %d\n",
dev->phy.hardware_power_control); dev->phy.hardware_power_control);
...@@ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, ...@@ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
list_for_each_entry(cal, &lo->calib_list, list) { list_for_each_entry(cal, &lo->calib_list, list) {
bool active; bool active;
active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
b43_compare_rfatt(&cal->rfatt, &phy->rfatt)); b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
"(expires in %lu sec)%s\n", "(expires in %lu sec)%s\n",
cal->bbatt.att, cal->bbatt.att,
...@@ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); ...@@ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);
B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
...@@ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) ...@@ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
ADD_FILE(mmio32write, 0200); ADD_FILE(mmio32write, 0200);
ADD_FILE(tsf, 0600); ADD_FILE(tsf, 0600);
ADD_FILE(txstat, 0400); ADD_FILE(txstat, 0400);
ADD_FILE(txpower_g, 0600);
ADD_FILE(restart, 0200); ADD_FILE(restart, 0200);
ADD_FILE(loctls, 0400); ADD_FILE(loctls, 0400);
...@@ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) ...@@ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
debugfs_remove(e->file_mmio32write.dentry); debugfs_remove(e->file_mmio32write.dentry);
debugfs_remove(e->file_tsf.dentry); debugfs_remove(e->file_tsf.dentry);
debugfs_remove(e->file_txstat.dentry); debugfs_remove(e->file_txstat.dentry);
debugfs_remove(e->file_txpower_g.dentry);
debugfs_remove(e->file_restart.dentry); debugfs_remove(e->file_restart.dentry);
debugfs_remove(e->file_loctls.dentry); debugfs_remove(e->file_loctls.dentry);
......
This diff is collapsed.
#ifndef B43_LO_H_ #ifndef B43_LO_H_
#define B43_LO_H_ #define B43_LO_H_
#include "phy.h" /* G-PHY Local Oscillator */
#include "phy_g.h"
struct b43_wldev; struct b43_wldev;
......
This diff is collapsed.
...@@ -81,9 +81,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) ...@@ -81,9 +81,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
//TODO //TODO
} }
/* Tune the hardware to a new channel. Don't call this directly. /* Tune the hardware to a new channel. */
* Use b43_radio_selectchannel() */ static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
{ {
const struct b43_nphy_channeltab_entry *tabent; const struct b43_nphy_channeltab_entry *tabent;
...@@ -162,7 +161,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) ...@@ -162,7 +161,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
msleep(1); msleep(1);
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
msleep(1); msleep(1);
b43_radio_selectchannel(dev, dev->phy.channel, 0); nphy_channel_switch(dev, dev->phy.channel);
b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
...@@ -484,3 +483,139 @@ int b43_phy_initn(struct b43_wldev *dev) ...@@ -484,3 +483,139 @@ int b43_phy_initn(struct b43_wldev *dev)
b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
return 0; return 0;
} }
static int b43_nphy_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_n *nphy;
nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
if (!nphy)
return -ENOMEM;
dev->phy.n = nphy;
//TODO init struct b43_phy_n
return 0;
}
static int b43_nphy_op_init(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
int err;
err = b43_phy_initn(dev);
if (err)
return err;
nphy->initialised = 1;
return 0;
}
static void b43_nphy_op_exit(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
if (nphy->initialised) {
//TODO
nphy->initialised = 0;
}
//TODO
kfree(nphy);
dev->phy.n = NULL;
}
static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
{
#if B43_DEBUG
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
/* OFDM registers are onnly available on A/G-PHYs */
b43err(dev->wl, "Invalid OFDM PHY access at "
"0x%04X on N-PHY\n", offset);
dump_stack();
}
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 N-PHY\n", offset);
dump_stack();
}
#endif /* B43_DEBUG */
}
static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
{
check_phyreg(dev, reg);
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
return b43_read16(dev, B43_MMIO_PHY_DATA);
}
static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
{
check_phyreg(dev, reg);
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA, value);
}
static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* Register 1 is a 32-bit register. */
B43_WARN_ON(reg == 1);
/* N-PHY needs 0x100 for read access */
reg |= 0x100;
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
}
static void b43_nphy_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 void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
enum rfkill_state state)
{//TODO
}
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
return -EINVAL;
} else {
if (new_channel > 200)
return -EINVAL;
}
return nphy_channel_switch(dev, new_channel);
}
static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
return 1;
return 36;
}
static void b43_nphy_op_xmitpower(struct b43_wldev *dev)
{//TODO
}
const struct b43_phy_operations b43_phyops_n = {
.allocate = b43_nphy_op_allocate,
.init = b43_nphy_op_init,
.exit = b43_nphy_op_exit,
.phy_read = b43_nphy_op_read,
.phy_write = b43_nphy_op_write,
.radio_read = b43_nphy_op_radio_read,
.radio_write = b43_nphy_op_radio_write,
.software_rfkill = b43_nphy_op_software_rfkill,
.switch_channel = b43_nphy_op_switch_channel,
.get_default_chan = b43_nphy_op_get_default_chan,
.xmitpower = b43_nphy_op_xmitpower,
};
#ifndef B43_NPHY_H_ #ifndef B43_NPHY_H_
#define B43_NPHY_H_ #define B43_NPHY_H_
#include "phy.h" #include "phy_common.h"
/* N-PHY registers. */ /* N-PHY registers. */
...@@ -919,54 +919,14 @@ ...@@ -919,54 +919,14 @@
struct b43_wldev; struct b43_wldev;
struct b43_phy_n {
bool initialised;
#ifdef CONFIG_B43_NPHY //TODO lots of missing stuff
/* N-PHY support enabled */ };
int b43_phy_initn(struct b43_wldev *dev);
void b43_nphy_radio_turn_on(struct b43_wldev *dev); struct b43_phy_operations;
void b43_nphy_radio_turn_off(struct b43_wldev *dev); extern const struct b43_phy_operations b43_phyops_n;
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
void b43_nphy_xmitpower(struct b43_wldev *dev);
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
#else /* CONFIG_B43_NPHY */
/* N-PHY support disabled */
static inline
int b43_phy_initn(struct b43_wldev *dev)
{
return -EOPNOTSUPP;
}
static inline
void b43_nphy_radio_turn_on(struct b43_wldev *dev)
{
}
static inline
void b43_nphy_radio_turn_off(struct b43_wldev *dev)
{
}
static inline
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
{
return -ENOSYS;
}
static inline
void b43_nphy_xmitpower(struct b43_wldev *dev)
{
}
static inline
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{
}
#endif /* CONFIG_B43_NPHY */
#endif /* B43_NPHY_H_ */ #endif /* B43_NPHY_H_ */
This diff is collapsed.
This diff is collapsed.
/*
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 <mb@bu3sch.de>
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 "nphy.h"
#include "b43.h"
#include "main.h"
int b43_phy_operations_setup(struct b43_wldev *dev)
{
struct b43_phy *phy = &(dev->phy);
int err;
phy->ops = NULL;
switch (phy->type) {
case B43_PHYTYPE_A:
phy->ops = &b43_phyops_a;
break;
case B43_PHYTYPE_G:
phy->ops = &b43_phyops_g;
break;
case B43_PHYTYPE_N:
#ifdef CONFIG_B43_NPHY
phy->ops = &b43_phyops_n;
#endif
break;
case B43_PHYTYPE_LP:
/* FIXME: Not yet */
break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
err = phy->ops->allocate(dev);
if (err)
phy->ops = NULL;
return err;
}
int b43_phy_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
const struct b43_phy_operations *ops = phy->ops;
int err;
phy->channel = ops->get_default_chan(dev);
ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
err = ops->init(dev);
if (err) {
b43err(dev->wl, "PHY init failed\n");
goto err_block_rf;
}
/* Make sure to switch hardware and firmware (SHM) to
* the default channel. */
err = b43_switch_channel(dev, ops->get_default_chan(dev));
if (err) {
b43err(dev->wl, "PHY init: Channel switch to default failed\n");
goto err_phy_exit;
}
return 0;
err_phy_exit:
if (ops->exit)
ops->exit(dev);
err_block_rf:
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
return err;
}
void b43_phy_exit(struct b43_wldev *dev)
{
const struct b43_phy_operations *ops = dev->phy.ops;
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
if (ops->exit)
ops->exit(dev);
}
bool b43_has_hardware_pctl(struct b43_wldev *dev)
{
if (!dev->phy.hardware_power_control)
return 0;
if (!dev->phy.ops->supports_hwpctl)
return 0;
return dev->phy.ops->supports_hwpctl(dev);
}
void b43_radio_lock(struct b43_wldev *dev)
{
u32 macctl;
macctl = b43_read32(dev, B43_MMIO_MACCTL);
B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
macctl |= B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit the write and wait for the device
* to exit any radio register access. */
b43_read32(dev, B43_MMIO_MACCTL);
udelay(10);
}
void b43_radio_unlock(struct b43_wldev *dev)
{
u32 macctl;
/* Commit any write */
b43_read16(dev, B43_MMIO_PHY_VER);
/* unlock */
macctl = b43_read32(dev, B43_MMIO_MACCTL);
B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
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 = 1;
#endif
B43_WARN_ON(dev->dev->id.revision < 3);
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_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 = 0;
#endif
B43_WARN_ON(dev->dev->id.revision < 3);
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
}
u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
{
return dev->phy.ops->radio_read(dev, reg);
}
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
{
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);
}
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
{
return dev->phy.ops->phy_read(dev, reg);
}
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
{
dev->phy.ops->phy_write(dev, reg, value);
}
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
{
b43_phy_write(dev, offset,
b43_phy_read(dev, offset) & mask);
}
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
{
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)
{
b43_phy_write(dev, offset,
(b43_phy_read(dev, offset) & mask) | set);
}
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
{
struct b43_phy *phy = &(dev->phy);
u16 channelcookie, savedcookie;
int err;
if (new_channel == B43_DEFAULT_CHANNEL)
new_channel = phy->ops->get_default_chan(dev);
/* 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 |= 0x100;
//FIXME set 40Mhz flag if required
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;
dev->phy.channel = new_channel;
/* 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, enum rfkill_state state)
{
struct b43_phy *phy = &dev->phy;
if (state == RFKILL_STATE_HARD_BLOCKED) {
/* We cannot hardware-block the device */
state = RFKILL_STATE_SOFT_BLOCKED;
}
phy->ops->software_rfkill(dev, state);
phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
}
#ifndef LINUX_B43_PHY_COMMON_H_
#define LINUX_B43_PHY_COMMON_H_
#include <linux/rfkill.h>
struct b43_wldev;
/* 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
/**
* 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, /* Antenna 0 */
B43_ANTENNA1, /* Antenna 0 */
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
B43_ANTENNA2,
B43_ANTENNA3 = 8,
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
};
/**
* struct b43_phy_operations - Function pointers for PHY ops.
*
* @prepare: Prepare the PHY. This is called before @init.
* Can be NULL, if not required.
* @init: Initialize the PHY.
* Must not be NULL.
* @exit: Shutdown the PHY and free all data structures.
* 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.
* @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_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.
*
* @xmitpower: FIXME REMOVEME
* Must not be NULL.
*
* @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);
int (*prepare)(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);
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, enum rfkill_state state);
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 */
void (*xmitpower)(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 {
/* 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;
};
/* Band support flags. */
bool supports_2ghz;
bool supports_5ghz;
/* GMODE bit enabled? */
bool gmode;
/* Analog Type */
u8 analog;
/* B43_PHYTYPE_ */
u8 type;
/* PHY revision number. */
u8 rev;
/* 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(). */
u8 power_level;
/* Hardware Power Control enabled? */
bool hardware_power_control;
/* current channel */
unsigned int channel;
/* PHY TX errors counter. */
atomic_t txerr_cnt;
#ifdef CONFIG_B43_DEBUG
/* PHY registers locked by b43_phy_lock()? */
bool phy_locked;
#endif /* B43_DEBUG */
};
/**
* b43_phy_operations_setup - Initialize the PHY operations datastructure
* based on the current PHY type.
*/
int b43_phy_operations_setup(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_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_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);
/**
* b43_switch_channel - Switch to another channel
*/
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
/**
* B43_DEFAULT_CHANNEL - Switch to the default channel.
*/
#define B43_DEFAULT_CHANNEL UINT_MAX
/**
* b43_software_rfkill - Turn the radio ON or OFF in software.
*/
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);
#endif /* LINUX_B43_PHY_COMMON_H_ */
This diff is collapsed.
#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 {
bool initialised;
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
/* 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];
/* TSSI to dBm table in use */
const s8 *tssi2dbm;
/* Target idle TSSI */
int tgt_idle_tssi;
/* Current idle TSSI */
int cur_idle_tssi;
/* 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 TX power level attenuation control values */
struct b43_bbatt bbatt;
struct b43_rfatt rfatt;
u8 tx_control; /* B43_TXCTL_XXX */
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
* Each value in the stack is layed 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);
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_g;
#endif /* LINUX_B43_PHY_G_H_ */
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "rfkill.h" #include "rfkill.h"
#include "b43.h" #include "b43.h"
#include "phy_common.h"
#include <linux/kmod.h> #include <linux/kmod.h>
...@@ -114,11 +115,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) ...@@ -114,11 +115,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
goto out_unlock; goto out_unlock;
} }
if (!dev->phy.radio_on) if (!dev->phy.radio_on)
b43_radio_turn_on(dev); b43_software_rfkill(dev, state);
break; break;
case RFKILL_STATE_SOFT_BLOCKED: case RFKILL_STATE_SOFT_BLOCKED:
if (dev->phy.radio_on) if (dev->phy.radio_on)
b43_radio_turn_off(dev, 0); b43_software_rfkill(dev, state);
break; break;
default: default:
b43warn(wl, "Received unexpected rfkill state %d.\n", state); b43warn(wl, "Received unexpected rfkill state %d.\n", state);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "b43.h" #include "b43.h"
#include "sysfs.h" #include "sysfs.h"
#include "main.h" #include "main.h"
#include "phy.h" #include "phy_common.h"
#define GENERIC_FILESIZE 64 #define GENERIC_FILESIZE 64
...@@ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev, ...@@ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev,
mutex_lock(&wldev->wl->mutex); mutex_lock(&wldev->wl->mutex);
switch (wldev->phy.interfmode) { if (wldev->phy.type != B43_PHYTYPE_G) {
mutex_unlock(&wldev->wl->mutex);
return -ENOSYS;
}
switch (wldev->phy.g->interfmode) {
case B43_INTERFMODE_NONE: case B43_INTERFMODE_NONE:
count = count =
snprintf(buf, PAGE_SIZE, snprintf(buf, PAGE_SIZE,
...@@ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, ...@@ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
mutex_lock(&wldev->wl->mutex); mutex_lock(&wldev->wl->mutex);
spin_lock_irqsave(&wldev->wl->irq_lock, flags); spin_lock_irqsave(&wldev->wl->irq_lock, flags);
err = b43_radio_set_interference_mitigation(wldev, mode); if (wldev->phy.ops->interf_mitigation) {
err = wldev->phy.ops->interf_mitigation(wldev, mode);
if (err) { if (err) {
b43err(wldev->wl, "Interference Mitigation not " b43err(wldev->wl, "Interference Mitigation not "
"supported by device\n"); "supported by device\n");
} }
} else
err = -ENOSYS;
mmiowb(); mmiowb();
spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
mutex_unlock(&wldev->wl->mutex); mutex_unlock(&wldev->wl->mutex);
......
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
#include "b43.h" #include "b43.h"
#include "tables.h" #include "tables.h"
#include "phy.h" #include "phy_g.h"
const u32 b43_tab_rotor[] = { const u32 b43_tab_rotor[] = {
0xFEB93FFD, 0xFEC63FFD, /* 0 */ 0xFEB93FFD, 0xFEC63FFD, /* 0 */
...@@ -377,17 +378,17 @@ static inline void assert_sizes(void) ...@@ -377,17 +378,17 @@ static inline void assert_sizes(void)
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = dev->phy.g;
u16 addr; u16 addr;
addr = table + offset; addr = table + offset;
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
(addr - 1 != phy->ofdmtab_addr)) { (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */ /* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr); b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
} }
phy->ofdmtab_addr = addr; gphy->ofdmtab_addr = addr;
return b43_phy_read(dev, B43_PHY_OTABLEI); return b43_phy_read(dev, B43_PHY_OTABLEI);
...@@ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) ...@@ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
u16 offset, u16 value) u16 offset, u16 value)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = dev->phy.g;
u16 addr; u16 addr;
addr = table + offset; addr = table + offset;
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
(addr - 1 != phy->ofdmtab_addr)) { (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */ /* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr); b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
} }
phy->ofdmtab_addr = addr; gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value); b43_phy_write(dev, B43_PHY_OTABLEI, value);
} }
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = dev->phy.g;
u32 ret; u32 ret;
u16 addr; u16 addr;
addr = table + offset; addr = table + offset;
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
(addr - 1 != phy->ofdmtab_addr)) { (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */ /* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr); b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
} }
phy->ofdmtab_addr = addr; gphy->ofdmtab_addr = addr;
ret = b43_phy_read(dev, B43_PHY_OTABLEQ); ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
ret <<= 16; ret <<= 16;
ret |= b43_phy_read(dev, B43_PHY_OTABLEI); ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
...@@ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) ...@@ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
u16 offset, u32 value) u16 offset, u32 value)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = dev->phy.g;
u16 addr; u16 addr;
addr = table + offset; addr = table + offset;
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
(addr - 1 != phy->ofdmtab_addr)) { (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */ /* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr); b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
} }
phy->ofdmtab_addr = addr; gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value); b43_phy_write(dev, B43_PHY_OTABLEI, value);
b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16)); b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "b43.h" #include "b43.h"
#include "tables_nphy.h" #include "tables_nphy.h"
#include "phy.h" #include "phy_common.h"
#include "nphy.h" #include "nphy.h"
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "b43.h" #include "b43.h"
#include "main.h" #include "main.h"
#include "tables.h" #include "tables.h"
#include "phy.h" #include "phy_common.h"
#include "wa.h" #include "wa.h"
static void b43_wa_papd(struct b43_wldev *dev) static void b43_wa_papd(struct b43_wldev *dev)
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
*/ */
#include "xmit.h" #include "xmit.h"
#include "phy.h" #include "phy_common.h"
#include "dma.h" #include "dma.h"
#include "pio.h" #include "pio.h"
...@@ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, ...@@ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
int adjust_2053, int adjust_2050) int adjust_2053, int adjust_2050)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
s32 tmp; s32 tmp;
switch (phy->radio_ver) { switch (phy->radio_ver) {
...@@ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, ...@@ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
boardflags_lo & B43_BFL_RSSI) { boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63) if (in_rssi > 63)
in_rssi = 63; in_rssi = 63;
tmp = phy->nrssi_lt[in_rssi]; B43_WARN_ON(phy->type != B43_PHYTYPE_G);
tmp = gphy->nrssi_lt[in_rssi];
tmp = 31 - tmp; tmp = 31 - tmp;
tmp *= -131; tmp *= -131;
tmp /= 128; tmp /= 128;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment