⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phy.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  Broadcom B43 wireless driver  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,  Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>  Copyright (c) 2005, 2006 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 <linux/delay.h>#include <linux/io.h>#include <linux/types.h>#include "b43.h"#include "phy.h"#include "main.h"#include "tables.h"#include "lo.h"static const s8 b43_tssi2dbm_b_table[] = {	0x4D, 0x4C, 0x4B, 0x4A,	0x4A, 0x49, 0x48, 0x47,	0x47, 0x46, 0x45, 0x45,	0x44, 0x43, 0x42, 0x42,	0x41, 0x40, 0x3F, 0x3E,	0x3D, 0x3C, 0x3B, 0x3A,	0x39, 0x38, 0x37, 0x36,	0x35, 0x34, 0x32, 0x31,	0x30, 0x2F, 0x2D, 0x2C,	0x2B, 0x29, 0x28, 0x26,	0x25, 0x23, 0x21, 0x1F,	0x1D, 0x1A, 0x17, 0x14,	0x10, 0x0C, 0x06, 0x00,	-7, -7, -7, -7,	-7, -7, -7, -7,	-7, -7, -7, -7,};static const s8 b43_tssi2dbm_g_table[] = {	77, 77, 77, 76,	76, 76, 75, 75,	74, 74, 73, 73,	73, 72, 72, 71,	71, 70, 70, 69,	68, 68, 67, 67,	66, 65, 65, 64,	63, 63, 62, 61,	60, 59, 58, 57,	56, 55, 54, 53,	52, 50, 49, 47,	45, 43, 40, 37,	33, 28, 22, 14,	5, -7, -20, -20,	-20, -20, -20, -20,	-20, -20, -20, -20,};const u8 b43_radio_channel_codes_bg[] = {	12, 17, 22, 27,	32, 37, 42, 47,	52, 57, 62, 67,	72, 84,};static void b43_phy_initg(struct b43_wldev *dev);/* Reverse the bits of a 4bit value. * Example:  1101 is flipped 1011 */static u16 flip_4bit(u16 value){	u16 flipped = 0x0000;	B43_WARN_ON(value & ~0x000F);	flipped |= (value & 0x0001) << 3;	flipped |= (value & 0x0002) << 1;	flipped |= (value & 0x0004) >> 1;	flipped |= (value & 0x0008) >> 3;	return flipped;}static void generate_rfatt_list(struct b43_wldev *dev,				struct b43_rfatt_list *list){	struct b43_phy *phy = &dev->phy;	/* APHY.rev < 5 || GPHY.rev < 6 */	static const struct b43_rfatt rfatt_0[] = {		{.att = 3,.with_padmix = 0,},		{.att = 1,.with_padmix = 0,},		{.att = 5,.with_padmix = 0,},		{.att = 7,.with_padmix = 0,},		{.att = 9,.with_padmix = 0,},		{.att = 2,.with_padmix = 0,},		{.att = 0,.with_padmix = 0,},		{.att = 4,.with_padmix = 0,},		{.att = 6,.with_padmix = 0,},		{.att = 8,.with_padmix = 0,},		{.att = 1,.with_padmix = 1,},		{.att = 2,.with_padmix = 1,},		{.att = 3,.with_padmix = 1,},		{.att = 4,.with_padmix = 1,},	};	/* Radio.rev == 8 && Radio.version == 0x2050 */	static const struct b43_rfatt rfatt_1[] = {		{.att = 2,.with_padmix = 1,},		{.att = 4,.with_padmix = 1,},		{.att = 6,.with_padmix = 1,},		{.att = 8,.with_padmix = 1,},		{.att = 10,.with_padmix = 1,},		{.att = 12,.with_padmix = 1,},		{.att = 14,.with_padmix = 1,},	};	/* Otherwise */	static const struct b43_rfatt rfatt_2[] = {		{.att = 0,.with_padmix = 1,},		{.att = 2,.with_padmix = 1,},		{.att = 4,.with_padmix = 1,},		{.att = 6,.with_padmix = 1,},		{.att = 8,.with_padmix = 1,},		{.att = 9,.with_padmix = 1,},		{.att = 9,.with_padmix = 1,},	};	if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) ||	    (phy->type == B43_PHYTYPE_G && phy->rev < 6)) {		/* Software pctl */		list->list = rfatt_0;		list->len = ARRAY_SIZE(rfatt_0);		list->min_val = 0;		list->max_val = 9;		return;	}	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {		/* Hardware pctl */		list->list = rfatt_1;		list->len = ARRAY_SIZE(rfatt_1);		list->min_val = 2;		list->max_val = 14;		return;	}	/* Hardware pctl */	list->list = rfatt_2;	list->len = ARRAY_SIZE(rfatt_2);	list->min_val = 0;	list->max_val = 9;}static void generate_bbatt_list(struct b43_wldev *dev,				struct b43_bbatt_list *list){	static const struct b43_bbatt bbatt_0[] = {		{.att = 0,},		{.att = 1,},		{.att = 2,},		{.att = 3,},		{.att = 4,},		{.att = 5,},		{.att = 6,},		{.att = 7,},		{.att = 8,},	};	list->list = bbatt_0;	list->len = ARRAY_SIZE(bbatt_0);	list->min_val = 0;	list->max_val = 8;}bool b43_has_hardware_pctl(struct b43_phy *phy){	if (!phy->hardware_power_control)		return 0;	switch (phy->type) {	case B43_PHYTYPE_A:		if (phy->rev >= 5)			return 1;		break;	case B43_PHYTYPE_G:		if (phy->rev >= 6)			return 1;		break;	default:		B43_WARN_ON(1);	}	return 0;}static void b43_shm_clear_tssi(struct b43_wldev *dev){	struct b43_phy *phy = &dev->phy;	switch (phy->type) {	case B43_PHYTYPE_A:		b43_shm_write16(dev, B43_SHM_SHARED, 0x0068, 0x7F7F);		b43_shm_write16(dev, B43_SHM_SHARED, 0x006a, 0x7F7F);		break;	case B43_PHYTYPE_B:	case B43_PHYTYPE_G:		b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);		b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);		b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);		b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);		break;	}}void b43_raw_phy_lock(struct b43_wldev *dev){	struct b43_phy *phy = &dev->phy;	B43_WARN_ON(!irqs_disabled());	/* We had a check for MACCTL==0 here, but I think that doesn't	 * make sense, as MACCTL is never 0 when this is called.	 *      --mb */	B43_WARN_ON(b43_read32(dev, B43_MMIO_MACCTL) == 0);	if (dev->dev->id.revision < 3) {		b43_mac_suspend(dev);		spin_lock(&phy->lock);	} else {		if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))			b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);	}	phy->locked = 1;}void b43_raw_phy_unlock(struct b43_wldev *dev){	struct b43_phy *phy = &dev->phy;	B43_WARN_ON(!irqs_disabled());	if (dev->dev->id.revision < 3) {		if (phy->locked) {			spin_unlock(&phy->lock);			b43_mac_enable(dev);		}	} else {		if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))			b43_power_saving_ctl_bits(dev, 0);	}	phy->locked = 0;}/* Different PHYs require different register routing flags. * This adjusts (and does sanity checks on) the routing flags. */static inline u16 adjust_phyreg_for_phytype(struct b43_phy *phy,					    u16 offset, struct b43_wldev *dev){	if (phy->type == B43_PHYTYPE_A) {		/* OFDM registers are base-registers for the A-PHY. */		offset &= ~B43_PHYROUTE_OFDM_GPHY;	}	if (offset & B43_PHYROUTE_EXT_GPHY) {		/* Ext-G registers are only available on G-PHYs */		if (phy->type != B43_PHYTYPE_G) {			b43dbg(dev->wl, "EXT-G PHY access at "			       "0x%04X on %u type PHY\n", offset, phy->type);		}	}	return offset;}u16 b43_phy_read(struct b43_wldev * dev, u16 offset){	struct b43_phy *phy = &dev->phy;	offset = adjust_phyreg_for_phytype(phy, offset, dev);	b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);	return b43_read16(dev, B43_MMIO_PHY_DATA);}void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val){	struct b43_phy *phy = &dev->phy;	offset = adjust_phyreg_for_phytype(phy, offset, dev);	b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);	mmiowb();	b43_write16(dev, B43_MMIO_PHY_DATA, val);}static void b43_radio_set_txpower_a(struct b43_wldev *dev, u16 txpower);/* Adjust the transmission power output (G-PHY) */void b43_set_txpower_g(struct b43_wldev *dev,		       const struct b43_bbatt *bbatt,		       const struct b43_rfatt *rfatt, u8 tx_control){	struct b43_phy *phy = &dev->phy;	struct b43_txpower_lo_control *lo = phy->lo_control;	u16 bb, rf;	u16 tx_bias, tx_magn;	bb = bbatt->att;	rf = rfatt->att;	tx_bias = lo->tx_bias;	tx_magn = lo->tx_magn;	if (unlikely(tx_bias == 0xFF))		tx_bias = 0;	/* Save the values for later */	phy->tx_control = tx_control;	memcpy(&phy->rfatt, rfatt, sizeof(*rfatt));	memcpy(&phy->bbatt, bbatt, sizeof(*bbatt));	if (b43_debug(dev, B43_DBG_XMITPOWER)) {		b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), "		       "rfatt(%u), tx_control(0x%02X), "		       "tx_bias(0x%02X), tx_magn(0x%02X)\n",		       bb, rf, tx_control, tx_bias, tx_magn);	}	b43_phy_set_baseband_attenuation(dev, bb);	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf);	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {		b43_radio_write16(dev, 0x43,				  (rf & 0x000F) | (tx_control & 0x0070));	} else {		b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)					      & 0xFFF0) | (rf & 0x000F));		b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)					      & ~0x0070) | (tx_control &							    0x0070));	}	if (has_tx_magnification(phy)) {		b43_radio_write16(dev, 0x52, tx_magn | tx_bias);	} else {		b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)					      & 0xFFF0) | (tx_bias & 0x000F));	}	if (phy->type == B43_PHYTYPE_G)		b43_lo_g_adjust(dev);}static void default_baseband_attenuation(struct b43_wldev *dev,					 struct b43_bbatt *bb){	struct b43_phy *phy = &dev->phy;	if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)		bb->att = 0;	else		bb->att = 2;}static void default_radio_attenuation(struct b43_wldev *dev,				      struct b43_rfatt *rf){	struct ssb_bus *bus = dev->dev->bus;	struct b43_phy *phy = &dev->phy;	rf->with_padmix = 0;	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&	    bus->boardinfo.type == SSB_BOARD_BCM4309G) {		if (bus->boardinfo.rev < 0x43) {			rf->att = 2;			return;		} else if (bus->boardinfo.rev < 0x51) {			rf->att = 3;			return;		}	}	if (phy->type == B43_PHYTYPE_A) {		rf->att = 0x60;		return;	}	switch (phy->radio_ver) {	case 0x2053:		switch (phy->radio_rev) {		case 1:			rf->att = 6;			return;		}		break;	case 0x2050:		switch (phy->radio_rev) {		case 0:			rf->att = 5;			return;		case 1:			if (phy->type == B43_PHYTYPE_G) {				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM				    && bus->boardinfo.type == SSB_BOARD_BCM4309G				    && bus->boardinfo.rev >= 30)					rf->att = 3;				else if (bus->boardinfo.vendor ==					 SSB_BOARDVENDOR_BCM					 && bus->boardinfo.type ==					 SSB_BOARD_BU4306)					rf->att = 3;				else					rf->att = 1;			} else {				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM				    && bus->boardinfo.type == SSB_BOARD_BCM4309G				    && bus->boardinfo.rev >= 30)					rf->att = 7;				else					rf->att = 6;			}			return;		case 2:			if (phy->type == B43_PHYTYPE_G) {				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM				    && bus->boardinfo.type == SSB_BOARD_BCM4309G				    && bus->boardinfo.rev >= 30)					rf->att = 3;				else if (bus->boardinfo.vendor ==					 SSB_BOARDVENDOR_BCM					 && bus->boardinfo.type ==					 SSB_BOARD_BU4306)					rf->att = 5;				else if (bus->chip_id == 0x4320)					rf->att = 4;				else					rf->att = 3;			} else				rf->att = 6;			return;		case 3:			rf->att = 5;			return;		case 4:		case 5:			rf->att = 1;			return;		case 6:		case 7:			rf->att = 5;			return;		case 8:			rf->att = 0xA;			rf->with_padmix = 1;			return;		case 9:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -