brintos

brintos / linux-shallow public Read only

0
0
Text · 81.0 KiB · ac72ca3 Raw
3058 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 4  Broadcom B43 wireless driver5  IEEE 802.11g PHY driver6 7  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,8  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>9  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>10  Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>11  Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>12 13 14*/15 16#include "b43.h"17#include "phy_g.h"18#include "phy_common.h"19#include "lo.h"20#include "main.h"21#include "wa.h"22 23#include <linux/bitrev.h>24#include <linux/slab.h>25 26 27static const s8 b43_tssi2dbm_g_table[] = {28	77, 77, 77, 76,29	76, 76, 75, 75,30	74, 74, 73, 73,31	73, 72, 72, 71,32	71, 70, 70, 69,33	68, 68, 67, 67,34	66, 65, 65, 64,35	63, 63, 62, 61,36	60, 59, 58, 57,37	56, 55, 54, 53,38	52, 50, 49, 47,39	45, 43, 40, 37,40	33, 28, 22, 14,41	5, -7, -20, -20,42	-20, -20, -20, -20,43	-20, -20, -20, -20,44};45 46static const u8 b43_radio_channel_codes_bg[] = {47	12, 17, 22, 27,48	32, 37, 42, 47,49	52, 57, 62, 67,50	72, 84,51};52 53 54static void b43_calc_nrssi_threshold(struct b43_wldev *dev);55 56 57#define bitrev4(tmp) (bitrev8(tmp) >> 4)58 59 60/* Get the freq, as it has to be written to the device. */61static inline u16 channel2freq_bg(u8 channel)62{63	B43_WARN_ON(!(channel >= 1 && channel <= 14));64 65	return b43_radio_channel_codes_bg[channel - 1];66}67 68static void generate_rfatt_list(struct b43_wldev *dev,69				struct b43_rfatt_list *list)70{71	struct b43_phy *phy = &dev->phy;72 73	/* APHY.rev < 5 || GPHY.rev < 6 */74	static const struct b43_rfatt rfatt_0[] = {75		{.att = 3,.with_padmix = 0,},76		{.att = 1,.with_padmix = 0,},77		{.att = 5,.with_padmix = 0,},78		{.att = 7,.with_padmix = 0,},79		{.att = 9,.with_padmix = 0,},80		{.att = 2,.with_padmix = 0,},81		{.att = 0,.with_padmix = 0,},82		{.att = 4,.with_padmix = 0,},83		{.att = 6,.with_padmix = 0,},84		{.att = 8,.with_padmix = 0,},85		{.att = 1,.with_padmix = 1,},86		{.att = 2,.with_padmix = 1,},87		{.att = 3,.with_padmix = 1,},88		{.att = 4,.with_padmix = 1,},89	};90	/* Radio.rev == 8 && Radio.version == 0x2050 */91	static const struct b43_rfatt rfatt_1[] = {92		{.att = 2,.with_padmix = 1,},93		{.att = 4,.with_padmix = 1,},94		{.att = 6,.with_padmix = 1,},95		{.att = 8,.with_padmix = 1,},96		{.att = 10,.with_padmix = 1,},97		{.att = 12,.with_padmix = 1,},98		{.att = 14,.with_padmix = 1,},99	};100	/* Otherwise */101	static const struct b43_rfatt rfatt_2[] = {102		{.att = 0,.with_padmix = 1,},103		{.att = 2,.with_padmix = 1,},104		{.att = 4,.with_padmix = 1,},105		{.att = 6,.with_padmix = 1,},106		{.att = 8,.with_padmix = 1,},107		{.att = 9,.with_padmix = 1,},108		{.att = 9,.with_padmix = 1,},109	};110 111	if (!b43_has_hardware_pctl(dev)) {112		/* Software pctl */113		list->list = rfatt_0;114		list->len = ARRAY_SIZE(rfatt_0);115		list->min_val = 0;116		list->max_val = 9;117		return;118	}119	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {120		/* Hardware pctl */121		list->list = rfatt_1;122		list->len = ARRAY_SIZE(rfatt_1);123		list->min_val = 0;124		list->max_val = 14;125		return;126	}127	/* Hardware pctl */128	list->list = rfatt_2;129	list->len = ARRAY_SIZE(rfatt_2);130	list->min_val = 0;131	list->max_val = 9;132}133 134static void generate_bbatt_list(struct b43_wldev *dev,135				struct b43_bbatt_list *list)136{137	static const struct b43_bbatt bbatt_0[] = {138		{.att = 0,},139		{.att = 1,},140		{.att = 2,},141		{.att = 3,},142		{.att = 4,},143		{.att = 5,},144		{.att = 6,},145		{.att = 7,},146		{.att = 8,},147	};148 149	list->list = bbatt_0;150	list->len = ARRAY_SIZE(bbatt_0);151	list->min_val = 0;152	list->max_val = 8;153}154 155static void b43_shm_clear_tssi(struct b43_wldev *dev)156{157	b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);158	b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);159	b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);160	b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);161}162 163/* Synthetic PU workaround */164static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel)165{166	struct b43_phy *phy = &dev->phy;167 168	might_sleep();169 170	if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {171		/* We do not need the workaround. */172		return;173	}174 175	if (channel <= 10) {176		b43_write16(dev, B43_MMIO_CHANNEL,177			    channel2freq_bg(channel + 4));178	} else {179		b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1));180	}181	msleep(1);182	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));183}184 185/* Set the baseband attenuation value on chip. */186void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,187				       u16 baseband_attenuation)188{189	struct b43_phy *phy = &dev->phy;190 191	if (phy->analog == 0) {192		b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0)193						 & 0xFFF0) |194			    baseband_attenuation);195	} else if (phy->analog > 1) {196		b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFFC3, (baseband_attenuation << 2));197	} else {198		b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFF87, (baseband_attenuation << 3));199	}200}201 202/* Adjust the transmission power output (G-PHY) */203static void b43_set_txpower_g(struct b43_wldev *dev,204			      const struct b43_bbatt *bbatt,205			      const struct b43_rfatt *rfatt, u8 tx_control)206{207	struct b43_phy *phy = &dev->phy;208	struct b43_phy_g *gphy = phy->g;209	struct b43_txpower_lo_control *lo = gphy->lo_control;210	u16 bb, rf;211	u16 tx_bias, tx_magn;212 213	bb = bbatt->att;214	rf = rfatt->att;215	tx_bias = lo->tx_bias;216	tx_magn = lo->tx_magn;217	if (unlikely(tx_bias == 0xFF))218		tx_bias = 0;219 220	/* Save the values for later. Use memmove, because it's valid221	 * to pass &gphy->rfatt as rfatt pointer argument. Same for bbatt. */222	gphy->tx_control = tx_control;223	memmove(&gphy->rfatt, rfatt, sizeof(*rfatt));224	gphy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);225	memmove(&gphy->bbatt, bbatt, sizeof(*bbatt));226 227	if (b43_debug(dev, B43_DBG_XMITPOWER)) {228		b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), "229		       "rfatt(%u), tx_control(0x%02X), "230		       "tx_bias(0x%02X), tx_magn(0x%02X)\n",231		       bb, rf, tx_control, tx_bias, tx_magn);232	}233 234	b43_gphy_set_baseband_attenuation(dev, bb);235	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf);236	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {237		b43_radio_write16(dev, 0x43,238				  (rf & 0x000F) | (tx_control & 0x0070));239	} else {240		b43_radio_maskset(dev, 0x43, 0xFFF0, (rf & 0x000F));241		b43_radio_maskset(dev, 0x52, ~0x0070, (tx_control & 0x0070));242	}243	if (has_tx_magnification(phy)) {244		b43_radio_write16(dev, 0x52, tx_magn | tx_bias);245	} else {246		b43_radio_maskset(dev, 0x52, 0xFFF0, (tx_bias & 0x000F));247	}248	b43_lo_g_adjust(dev);249}250 251/* GPHY_TSSI_Power_Lookup_Table_Init */252static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev)253{254	struct b43_phy_g *gphy = dev->phy.g;255	int i;256	u16 value;257 258	for (i = 0; i < 32; i++)259		b43_ofdmtab_write16(dev, 0x3C20, i, gphy->tssi2dbm[i]);260	for (i = 32; i < 64; i++)261		b43_ofdmtab_write16(dev, 0x3C00, i - 32, gphy->tssi2dbm[i]);262	for (i = 0; i < 64; i += 2) {263		value = (u16) gphy->tssi2dbm[i];264		value |= ((u16) gphy->tssi2dbm[i + 1]) << 8;265		b43_phy_write(dev, 0x380 + (i / 2), value);266	}267}268 269/* GPHY_Gain_Lookup_Table_Init */270static void b43_gphy_gain_lt_init(struct b43_wldev *dev)271{272	struct b43_phy *phy = &dev->phy;273	struct b43_phy_g *gphy = phy->g;274	struct b43_txpower_lo_control *lo = gphy->lo_control;275	u16 nr_written = 0;276	u16 tmp;277	u8 rf, bb;278 279	for (rf = 0; rf < lo->rfatt_list.len; rf++) {280		for (bb = 0; bb < lo->bbatt_list.len; bb++) {281			if (nr_written >= 0x40)282				return;283			tmp = lo->bbatt_list.list[bb].att;284			tmp <<= 8;285			if (phy->radio_rev == 8)286				tmp |= 0x50;287			else288				tmp |= 0x40;289			tmp |= lo->rfatt_list.list[rf].att;290			b43_phy_write(dev, 0x3C0 + nr_written, tmp);291			nr_written++;292		}293	}294}295 296static void b43_set_all_gains(struct b43_wldev *dev,297			      s16 first, s16 second, s16 third)298{299	struct b43_phy *phy = &dev->phy;300	u16 i;301	u16 start = 0x08, end = 0x18;302	u16 tmp;303	u16 table;304 305	if (phy->rev <= 1) {306		start = 0x10;307		end = 0x20;308	}309 310	table = B43_OFDMTAB_GAINX;311	if (phy->rev <= 1)312		table = B43_OFDMTAB_GAINX_R1;313	for (i = 0; i < 4; i++)314		b43_ofdmtab_write16(dev, table, i, first);315 316	for (i = start; i < end; i++)317		b43_ofdmtab_write16(dev, table, i, second);318 319	if (third != -1) {320		tmp = ((u16) third << 14) | ((u16) third << 6);321		b43_phy_maskset(dev, 0x04A0, 0xBFBF, tmp);322		b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp);323		b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp);324	}325	b43_dummy_transmission(dev, false, true);326}327 328static void b43_set_original_gains(struct b43_wldev *dev)329{330	struct b43_phy *phy = &dev->phy;331	u16 i, tmp;332	u16 table;333	u16 start = 0x0008, end = 0x0018;334 335	if (phy->rev <= 1) {336		start = 0x0010;337		end = 0x0020;338	}339 340	table = B43_OFDMTAB_GAINX;341	if (phy->rev <= 1)342		table = B43_OFDMTAB_GAINX_R1;343	for (i = 0; i < 4; i++) {344		tmp = (i & 0xFFFC);345		tmp |= (i & 0x0001) << 1;346		tmp |= (i & 0x0002) >> 1;347 348		b43_ofdmtab_write16(dev, table, i, tmp);349	}350 351	for (i = start; i < end; i++)352		b43_ofdmtab_write16(dev, table, i, i - start);353 354	b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040);355	b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040);356	b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000);357	b43_dummy_transmission(dev, false, true);358}359 360/* https://bcm-specs.sipsolutions.net/NRSSILookupTable */361static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)362{363	b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);364	b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);365}366 367/* https://bcm-specs.sipsolutions.net/NRSSILookupTable */368static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)369{370	u16 val;371 372	b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);373	val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA);374 375	return (s16) val;376}377 378/* https://bcm-specs.sipsolutions.net/NRSSILookupTable */379static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)380{381	u16 i;382	s16 tmp;383 384	for (i = 0; i < 64; i++) {385		tmp = b43_nrssi_hw_read(dev, i);386		tmp -= val;387		tmp = clamp_val(tmp, -32, 31);388		b43_nrssi_hw_write(dev, i, tmp);389	}390}391 392/* https://bcm-specs.sipsolutions.net/NRSSILookupTable */393static void b43_nrssi_mem_update(struct b43_wldev *dev)394{395	struct b43_phy_g *gphy = dev->phy.g;396	s16 i, delta;397	s32 tmp;398 399	delta = 0x1F - gphy->nrssi[0];400	for (i = 0; i < 64; i++) {401		tmp = (i - delta) * gphy->nrssislope;402		tmp /= 0x10000;403		tmp += 0x3A;404		tmp = clamp_val(tmp, 0, 0x3F);405		gphy->nrssi_lt[i] = tmp;406	}407}408 409static void b43_calc_nrssi_offset(struct b43_wldev *dev)410{411	struct b43_phy *phy = &dev->phy;412	u16 backup[20] = { 0 };413	s16 v47F;414	u16 i;415	u16 saved = 0xFFFF;416 417	backup[0] = b43_phy_read(dev, 0x0001);418	backup[1] = b43_phy_read(dev, 0x0811);419	backup[2] = b43_phy_read(dev, 0x0812);420	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */421		backup[3] = b43_phy_read(dev, 0x0814);422		backup[4] = b43_phy_read(dev, 0x0815);423	}424	backup[5] = b43_phy_read(dev, 0x005A);425	backup[6] = b43_phy_read(dev, 0x0059);426	backup[7] = b43_phy_read(dev, 0x0058);427	backup[8] = b43_phy_read(dev, 0x000A);428	backup[9] = b43_phy_read(dev, 0x0003);429	backup[10] = b43_radio_read16(dev, 0x007A);430	backup[11] = b43_radio_read16(dev, 0x0043);431 432	b43_phy_mask(dev, 0x0429, 0x7FFF);433	b43_phy_maskset(dev, 0x0001, 0x3FFF, 0x4000);434	b43_phy_set(dev, 0x0811, 0x000C);435	b43_phy_maskset(dev, 0x0812, 0xFFF3, 0x0004);436	b43_phy_mask(dev, 0x0802, ~(0x1 | 0x2));437	if (phy->rev >= 6) {438		backup[12] = b43_phy_read(dev, 0x002E);439		backup[13] = b43_phy_read(dev, 0x002F);440		backup[14] = b43_phy_read(dev, 0x080F);441		backup[15] = b43_phy_read(dev, 0x0810);442		backup[16] = b43_phy_read(dev, 0x0801);443		backup[17] = b43_phy_read(dev, 0x0060);444		backup[18] = b43_phy_read(dev, 0x0014);445		backup[19] = b43_phy_read(dev, 0x0478);446 447		b43_phy_write(dev, 0x002E, 0);448		b43_phy_write(dev, 0x002F, 0);449		b43_phy_write(dev, 0x080F, 0);450		b43_phy_write(dev, 0x0810, 0);451		b43_phy_set(dev, 0x0478, 0x0100);452		b43_phy_set(dev, 0x0801, 0x0040);453		b43_phy_set(dev, 0x0060, 0x0040);454		b43_phy_set(dev, 0x0014, 0x0200);455	}456	b43_radio_set(dev, 0x007A, 0x0070);457	b43_radio_set(dev, 0x007A, 0x0080);458	udelay(30);459 460	v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);461	if (v47F >= 0x20)462		v47F -= 0x40;463	if (v47F == 31) {464		for (i = 7; i >= 4; i--) {465			b43_radio_write16(dev, 0x007B, i);466			udelay(20);467			v47F =468			    (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);469			if (v47F >= 0x20)470				v47F -= 0x40;471			if (v47F < 31 && saved == 0xFFFF)472				saved = i;473		}474		if (saved == 0xFFFF)475			saved = 4;476	} else {477		b43_radio_mask(dev, 0x007A, 0x007F);478		if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */479			b43_phy_set(dev, 0x0814, 0x0001);480			b43_phy_mask(dev, 0x0815, 0xFFFE);481		}482		b43_phy_set(dev, 0x0811, 0x000C);483		b43_phy_set(dev, 0x0812, 0x000C);484		b43_phy_set(dev, 0x0811, 0x0030);485		b43_phy_set(dev, 0x0812, 0x0030);486		b43_phy_write(dev, 0x005A, 0x0480);487		b43_phy_write(dev, 0x0059, 0x0810);488		b43_phy_write(dev, 0x0058, 0x000D);489		if (phy->rev == 0) {490			b43_phy_write(dev, 0x0003, 0x0122);491		} else {492			b43_phy_set(dev, 0x000A, 0x2000);493		}494		if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */495			b43_phy_set(dev, 0x0814, 0x0004);496			b43_phy_mask(dev, 0x0815, 0xFFFB);497		}498		b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040);499		b43_radio_set(dev, 0x007A, 0x000F);500		b43_set_all_gains(dev, 3, 0, 1);501		b43_radio_maskset(dev, 0x0043, 0x00F0, 0x000F);502		udelay(30);503		v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);504		if (v47F >= 0x20)505			v47F -= 0x40;506		if (v47F == -32) {507			for (i = 0; i < 4; i++) {508				b43_radio_write16(dev, 0x007B, i);509				udelay(20);510				v47F =511				    (s16) ((b43_phy_read(dev, 0x047F) >> 8) &512					   0x003F);513				if (v47F >= 0x20)514					v47F -= 0x40;515				if (v47F > -31 && saved == 0xFFFF)516					saved = i;517			}518			if (saved == 0xFFFF)519				saved = 3;520		} else521			saved = 0;522	}523	b43_radio_write16(dev, 0x007B, saved);524 525	if (phy->rev >= 6) {526		b43_phy_write(dev, 0x002E, backup[12]);527		b43_phy_write(dev, 0x002F, backup[13]);528		b43_phy_write(dev, 0x080F, backup[14]);529		b43_phy_write(dev, 0x0810, backup[15]);530	}531	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */532		b43_phy_write(dev, 0x0814, backup[3]);533		b43_phy_write(dev, 0x0815, backup[4]);534	}535	b43_phy_write(dev, 0x005A, backup[5]);536	b43_phy_write(dev, 0x0059, backup[6]);537	b43_phy_write(dev, 0x0058, backup[7]);538	b43_phy_write(dev, 0x000A, backup[8]);539	b43_phy_write(dev, 0x0003, backup[9]);540	b43_radio_write16(dev, 0x0043, backup[11]);541	b43_radio_write16(dev, 0x007A, backup[10]);542	b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2);543	b43_phy_set(dev, 0x0429, 0x8000);544	b43_set_original_gains(dev);545	if (phy->rev >= 6) {546		b43_phy_write(dev, 0x0801, backup[16]);547		b43_phy_write(dev, 0x0060, backup[17]);548		b43_phy_write(dev, 0x0014, backup[18]);549		b43_phy_write(dev, 0x0478, backup[19]);550	}551	b43_phy_write(dev, 0x0001, backup[0]);552	b43_phy_write(dev, 0x0812, backup[2]);553	b43_phy_write(dev, 0x0811, backup[1]);554}555 556static void b43_calc_nrssi_slope(struct b43_wldev *dev)557{558	struct b43_phy *phy = &dev->phy;559	struct b43_phy_g *gphy = phy->g;560	u16 backup[18] = { 0 };561	u16 tmp;562	s16 nrssi0, nrssi1;563 564	B43_WARN_ON(phy->type != B43_PHYTYPE_G);565 566	if (phy->radio_rev >= 9)567		return;568	if (phy->radio_rev == 8)569		b43_calc_nrssi_offset(dev);570 571	b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);572	b43_phy_mask(dev, 0x0802, 0xFFFC);573	backup[7] = b43_read16(dev, 0x03E2);574	b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000);575	backup[0] = b43_radio_read16(dev, 0x007A);576	backup[1] = b43_radio_read16(dev, 0x0052);577	backup[2] = b43_radio_read16(dev, 0x0043);578	backup[3] = b43_phy_read(dev, 0x0015);579	backup[4] = b43_phy_read(dev, 0x005A);580	backup[5] = b43_phy_read(dev, 0x0059);581	backup[6] = b43_phy_read(dev, 0x0058);582	backup[8] = b43_read16(dev, 0x03E6);583	backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);584	if (phy->rev >= 3) {585		backup[10] = b43_phy_read(dev, 0x002E);586		backup[11] = b43_phy_read(dev, 0x002F);587		backup[12] = b43_phy_read(dev, 0x080F);588		backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL);589		backup[14] = b43_phy_read(dev, 0x0801);590		backup[15] = b43_phy_read(dev, 0x0060);591		backup[16] = b43_phy_read(dev, 0x0014);592		backup[17] = b43_phy_read(dev, 0x0478);593		b43_phy_write(dev, 0x002E, 0);594		b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0);595		switch (phy->rev) {596		case 4:597		case 6:598		case 7:599			b43_phy_set(dev, 0x0478, 0x0100);600			b43_phy_set(dev, 0x0801, 0x0040);601			break;602		case 3:603		case 5:604			b43_phy_mask(dev, 0x0801, 0xFFBF);605			break;606		}607		b43_phy_set(dev, 0x0060, 0x0040);608		b43_phy_set(dev, 0x0014, 0x0200);609	}610	b43_radio_set(dev, 0x007A, 0x0070);611	b43_set_all_gains(dev, 0, 8, 0);612	b43_radio_mask(dev, 0x007A, 0x00F7);613	if (phy->rev >= 2) {614		b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0030);615		b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0010);616	}617	b43_radio_set(dev, 0x007A, 0x0080);618	udelay(20);619 620	nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);621	if (nrssi0 >= 0x0020)622		nrssi0 -= 0x0040;623 624	b43_radio_mask(dev, 0x007A, 0x007F);625	if (phy->rev >= 2) {626		b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040);627	}628 629	b43_write16(dev, B43_MMIO_CHANNEL_EXT,630		    b43_read16(dev, B43_MMIO_CHANNEL_EXT)631		    | 0x2000);632	b43_radio_set(dev, 0x007A, 0x000F);633	b43_phy_write(dev, 0x0015, 0xF330);634	if (phy->rev >= 2) {635		b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0020);636		b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0020);637	}638 639	b43_set_all_gains(dev, 3, 0, 1);640	if (phy->radio_rev == 8) {641		b43_radio_write16(dev, 0x0043, 0x001F);642	} else {643		tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F;644		b43_radio_write16(dev, 0x0052, tmp | 0x0060);645		tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0;646		b43_radio_write16(dev, 0x0043, tmp | 0x0009);647	}648	b43_phy_write(dev, 0x005A, 0x0480);649	b43_phy_write(dev, 0x0059, 0x0810);650	b43_phy_write(dev, 0x0058, 0x000D);651	udelay(20);652	nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);653	if (nrssi1 >= 0x0020)654		nrssi1 -= 0x0040;655	if (nrssi0 == nrssi1)656		gphy->nrssislope = 0x00010000;657	else658		gphy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);659	if (nrssi0 >= -4) {660		gphy->nrssi[0] = nrssi1;661		gphy->nrssi[1] = nrssi0;662	}663	if (phy->rev >= 3) {664		b43_phy_write(dev, 0x002E, backup[10]);665		b43_phy_write(dev, 0x002F, backup[11]);666		b43_phy_write(dev, 0x080F, backup[12]);667		b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]);668	}669	if (phy->rev >= 2) {670		b43_phy_mask(dev, 0x0812, 0xFFCF);671		b43_phy_mask(dev, 0x0811, 0xFFCF);672	}673 674	b43_radio_write16(dev, 0x007A, backup[0]);675	b43_radio_write16(dev, 0x0052, backup[1]);676	b43_radio_write16(dev, 0x0043, backup[2]);677	b43_write16(dev, 0x03E2, backup[7]);678	b43_write16(dev, 0x03E6, backup[8]);679	b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]);680	b43_phy_write(dev, 0x0015, backup[3]);681	b43_phy_write(dev, 0x005A, backup[4]);682	b43_phy_write(dev, 0x0059, backup[5]);683	b43_phy_write(dev, 0x0058, backup[6]);684	b43_synth_pu_workaround(dev, phy->channel);685	b43_phy_set(dev, 0x0802, (0x0001 | 0x0002));686	b43_set_original_gains(dev);687	b43_phy_set(dev, B43_PHY_G_CRS, 0x8000);688	if (phy->rev >= 3) {689		b43_phy_write(dev, 0x0801, backup[14]);690		b43_phy_write(dev, 0x0060, backup[15]);691		b43_phy_write(dev, 0x0014, backup[16]);692		b43_phy_write(dev, 0x0478, backup[17]);693	}694	b43_nrssi_mem_update(dev);695	b43_calc_nrssi_threshold(dev);696}697 698static void b43_calc_nrssi_threshold(struct b43_wldev *dev)699{700	struct b43_phy *phy = &dev->phy;701	struct b43_phy_g *gphy = phy->g;702	s32 a, b;703	s16 tmp16;704	u16 tmp_u16;705 706	B43_WARN_ON(phy->type != B43_PHYTYPE_G);707 708	if (!phy->gmode ||709	    !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {710		tmp16 = b43_nrssi_hw_read(dev, 0x20);711		if (tmp16 >= 0x20)712			tmp16 -= 0x40;713		if (tmp16 < 3) {714			b43_phy_maskset(dev, 0x048A, 0xF000, 0x09EB);715		} else {716			b43_phy_maskset(dev, 0x048A, 0xF000, 0x0AED);717		}718	} else {719		if (gphy->interfmode == B43_INTERFMODE_NONWLAN) {720			a = 0xE;721			b = 0xA;722		} else if (!gphy->aci_wlan_automatic && gphy->aci_enable) {723			a = 0x13;724			b = 0x12;725		} else {726			a = 0xE;727			b = 0x11;728		}729 730		a = a * (gphy->nrssi[1] - gphy->nrssi[0]);731		a += (gphy->nrssi[0] << 6);732		if (a < 32)733			a += 31;734		else735			a += 32;736		a = a >> 6;737		a = clamp_val(a, -31, 31);738 739		b = b * (gphy->nrssi[1] - gphy->nrssi[0]);740		b += (gphy->nrssi[0] << 6);741		if (b < 32)742			b += 31;743		else744			b += 32;745		b = b >> 6;746		b = clamp_val(b, -31, 31);747 748		tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;749		tmp_u16 |= ((u32) b & 0x0000003F);750		tmp_u16 |= (((u32) a & 0x0000003F) << 6);751		b43_phy_write(dev, 0x048A, tmp_u16);752	}753}754 755/* Stack implementation to save/restore values from the756 * interference mitigation code.757 * It is save to restore values in random order.758 */759static void _stack_save(u32 *_stackptr, size_t *stackidx,760			u8 id, u16 offset, u16 value)761{762	u32 *stackptr = &(_stackptr[*stackidx]);763 764	B43_WARN_ON(offset & 0xF000);765	B43_WARN_ON(id & 0xF0);766	*stackptr = offset;767	*stackptr |= ((u32) id) << 12;768	*stackptr |= ((u32) value) << 16;769	(*stackidx)++;770	B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE);771}772 773static u16 _stack_restore(u32 *stackptr, u8 id, u16 offset)774{775	size_t i;776 777	B43_WARN_ON(offset & 0xF000);778	B43_WARN_ON(id & 0xF0);779	for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) {780		if ((*stackptr & 0x00000FFF) != offset)781			continue;782		if (((*stackptr & 0x0000F000) >> 12) != id)783			continue;784		return ((*stackptr & 0xFFFF0000) >> 16);785	}786	B43_WARN_ON(1);787 788	return 0;789}790 791#define phy_stacksave(offset)					\792	do {							\793		_stack_save(stack, &stackidx, 0x1, (offset),	\794			    b43_phy_read(dev, (offset)));	\795	} while (0)796#define phy_stackrestore(offset)				\797	do {							\798		b43_phy_write(dev, (offset),		\799				  _stack_restore(stack, 0x1,	\800						 (offset)));	\801	} while (0)802#define radio_stacksave(offset)						\803	do {								\804		_stack_save(stack, &stackidx, 0x2, (offset),		\805			    b43_radio_read16(dev, (offset)));	\806	} while (0)807#define radio_stackrestore(offset)					\808	do {								\809		b43_radio_write16(dev, (offset),			\810				      _stack_restore(stack, 0x2,	\811						     (offset)));	\812	} while (0)813#define ofdmtab_stacksave(table, offset)			\814	do {							\815		_stack_save(stack, &stackidx, 0x3, (offset)|(table),	\816			    b43_ofdmtab_read16(dev, (table), (offset)));	\817	} while (0)818#define ofdmtab_stackrestore(table, offset)			\819	do {							\820		b43_ofdmtab_write16(dev, (table),	(offset),	\821				  _stack_restore(stack, 0x3,	\822						 (offset)|(table)));	\823	} while (0)824 825static void826b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)827{828	struct b43_phy *phy = &dev->phy;829	struct b43_phy_g *gphy = phy->g;830	u16 tmp, flipped;831	size_t stackidx = 0;832	u32 *stack = gphy->interfstack;833 834	switch (mode) {835	case B43_INTERFMODE_NONWLAN:836		if (phy->rev != 1) {837			b43_phy_set(dev, 0x042B, 0x0800);838			b43_phy_mask(dev, B43_PHY_G_CRS, ~0x4000);839			break;840		}841		radio_stacksave(0x0078);842		tmp = (b43_radio_read16(dev, 0x0078) & 0x001E);843		B43_WARN_ON(tmp > 15);844		flipped = bitrev4(tmp);845		if (flipped < 10 && flipped >= 8)846			flipped = 7;847		else if (flipped >= 10)848			flipped -= 3;849		flipped = (bitrev4(flipped) << 1) | 0x0020;850		b43_radio_write16(dev, 0x0078, flipped);851 852		b43_calc_nrssi_threshold(dev);853 854		phy_stacksave(0x0406);855		b43_phy_write(dev, 0x0406, 0x7E28);856 857		b43_phy_set(dev, 0x042B, 0x0800);858		b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, 0x1000);859 860		phy_stacksave(0x04A0);861		b43_phy_maskset(dev, 0x04A0, 0xC0C0, 0x0008);862		phy_stacksave(0x04A1);863		b43_phy_maskset(dev, 0x04A1, 0xC0C0, 0x0605);864		phy_stacksave(0x04A2);865		b43_phy_maskset(dev, 0x04A2, 0xC0C0, 0x0204);866		phy_stacksave(0x04A8);867		b43_phy_maskset(dev, 0x04A8, 0xC0C0, 0x0803);868		phy_stacksave(0x04AB);869		b43_phy_maskset(dev, 0x04AB, 0xC0C0, 0x0605);870 871		phy_stacksave(0x04A7);872		b43_phy_write(dev, 0x04A7, 0x0002);873		phy_stacksave(0x04A3);874		b43_phy_write(dev, 0x04A3, 0x287A);875		phy_stacksave(0x04A9);876		b43_phy_write(dev, 0x04A9, 0x2027);877		phy_stacksave(0x0493);878		b43_phy_write(dev, 0x0493, 0x32F5);879		phy_stacksave(0x04AA);880		b43_phy_write(dev, 0x04AA, 0x2027);881		phy_stacksave(0x04AC);882		b43_phy_write(dev, 0x04AC, 0x32F5);883		break;884	case B43_INTERFMODE_MANUALWLAN:885		if (b43_phy_read(dev, 0x0033) & 0x0800)886			break;887 888		gphy->aci_enable = true;889 890		phy_stacksave(B43_PHY_RADIO_BITFIELD);891		phy_stacksave(B43_PHY_G_CRS);892		if (phy->rev < 2) {893			phy_stacksave(0x0406);894		} else {895			phy_stacksave(0x04C0);896			phy_stacksave(0x04C1);897		}898		phy_stacksave(0x0033);899		phy_stacksave(0x04A7);900		phy_stacksave(0x04A3);901		phy_stacksave(0x04A9);902		phy_stacksave(0x04AA);903		phy_stacksave(0x04AC);904		phy_stacksave(0x0493);905		phy_stacksave(0x04A1);906		phy_stacksave(0x04A0);907		phy_stacksave(0x04A2);908		phy_stacksave(0x048A);909		phy_stacksave(0x04A8);910		phy_stacksave(0x04AB);911		if (phy->rev == 2) {912			phy_stacksave(0x04AD);913			phy_stacksave(0x04AE);914		} else if (phy->rev >= 3) {915			phy_stacksave(0x04AD);916			phy_stacksave(0x0415);917			phy_stacksave(0x0416);918			phy_stacksave(0x0417);919			ofdmtab_stacksave(0x1A00, 0x2);920			ofdmtab_stacksave(0x1A00, 0x3);921		}922		phy_stacksave(0x042B);923		phy_stacksave(0x048C);924 925		b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~0x1000);926		b43_phy_maskset(dev, B43_PHY_G_CRS, 0xFFFC, 0x0002);927 928		b43_phy_write(dev, 0x0033, 0x0800);929		b43_phy_write(dev, 0x04A3, 0x2027);930		b43_phy_write(dev, 0x04A9, 0x1CA8);931		b43_phy_write(dev, 0x0493, 0x287A);932		b43_phy_write(dev, 0x04AA, 0x1CA8);933		b43_phy_write(dev, 0x04AC, 0x287A);934 935		b43_phy_maskset(dev, 0x04A0, 0xFFC0, 0x001A);936		b43_phy_write(dev, 0x04A7, 0x000D);937 938		if (phy->rev < 2) {939			b43_phy_write(dev, 0x0406, 0xFF0D);940		} else if (phy->rev == 2) {941			b43_phy_write(dev, 0x04C0, 0xFFFF);942			b43_phy_write(dev, 0x04C1, 0x00A9);943		} else {944			b43_phy_write(dev, 0x04C0, 0x00C1);945			b43_phy_write(dev, 0x04C1, 0x0059);946		}947 948		b43_phy_maskset(dev, 0x04A1, 0xC0FF, 0x1800);949		b43_phy_maskset(dev, 0x04A1, 0xFFC0, 0x0015);950		b43_phy_maskset(dev, 0x04A8, 0xCFFF, 0x1000);951		b43_phy_maskset(dev, 0x04A8, 0xF0FF, 0x0A00);952		b43_phy_maskset(dev, 0x04AB, 0xCFFF, 0x1000);953		b43_phy_maskset(dev, 0x04AB, 0xF0FF, 0x0800);954		b43_phy_maskset(dev, 0x04AB, 0xFFCF, 0x0010);955		b43_phy_maskset(dev, 0x04AB, 0xFFF0, 0x0005);956		b43_phy_maskset(dev, 0x04A8, 0xFFCF, 0x0010);957		b43_phy_maskset(dev, 0x04A8, 0xFFF0, 0x0006);958		b43_phy_maskset(dev, 0x04A2, 0xF0FF, 0x0800);959		b43_phy_maskset(dev, 0x04A0, 0xF0FF, 0x0500);960		b43_phy_maskset(dev, 0x04A2, 0xFFF0, 0x000B);961 962		if (phy->rev >= 3) {963			b43_phy_mask(dev, 0x048A, 0x7FFF);964			b43_phy_maskset(dev, 0x0415, 0x8000, 0x36D8);965			b43_phy_maskset(dev, 0x0416, 0x8000, 0x36D8);966			b43_phy_maskset(dev, 0x0417, 0xFE00, 0x016D);967		} else {968			b43_phy_set(dev, 0x048A, 0x1000);969			b43_phy_maskset(dev, 0x048A, 0x9FFF, 0x2000);970			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW);971		}972		if (phy->rev >= 2) {973			b43_phy_set(dev, 0x042B, 0x0800);974		}975		b43_phy_maskset(dev, 0x048C, 0xF0FF, 0x0200);976		if (phy->rev == 2) {977			b43_phy_maskset(dev, 0x04AE, 0xFF00, 0x007F);978			b43_phy_maskset(dev, 0x04AD, 0x00FF, 0x1300);979		} else if (phy->rev >= 6) {980			b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F);981			b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F);982			b43_phy_mask(dev, 0x04AD, 0x00FF);983		}984		b43_calc_nrssi_slope(dev);985		break;986	default:987		B43_WARN_ON(1);988	}989}990 991static void992b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)993{994	struct b43_phy *phy = &dev->phy;995	struct b43_phy_g *gphy = phy->g;996	u32 *stack = gphy->interfstack;997 998	switch (mode) {999	case B43_INTERFMODE_NONWLAN:1000		if (phy->rev != 1) {1001			b43_phy_mask(dev, 0x042B, ~0x0800);1002			b43_phy_set(dev, B43_PHY_G_CRS, 0x4000);1003			break;1004		}1005		radio_stackrestore(0x0078);1006		b43_calc_nrssi_threshold(dev);1007		phy_stackrestore(0x0406);1008		b43_phy_mask(dev, 0x042B, ~0x0800);1009		if (!dev->bad_frames_preempt) {1010			b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~(1 << 11));1011		}1012		b43_phy_set(dev, B43_PHY_G_CRS, 0x4000);1013		phy_stackrestore(0x04A0);1014		phy_stackrestore(0x04A1);1015		phy_stackrestore(0x04A2);1016		phy_stackrestore(0x04A8);1017		phy_stackrestore(0x04AB);1018		phy_stackrestore(0x04A7);1019		phy_stackrestore(0x04A3);1020		phy_stackrestore(0x04A9);1021		phy_stackrestore(0x0493);1022		phy_stackrestore(0x04AA);1023		phy_stackrestore(0x04AC);1024		break;1025	case B43_INTERFMODE_MANUALWLAN:1026		if (!(b43_phy_read(dev, 0x0033) & 0x0800))1027			break;1028 1029		gphy->aci_enable = false;1030 1031		phy_stackrestore(B43_PHY_RADIO_BITFIELD);1032		phy_stackrestore(B43_PHY_G_CRS);1033		phy_stackrestore(0x0033);1034		phy_stackrestore(0x04A3);1035		phy_stackrestore(0x04A9);1036		phy_stackrestore(0x0493);1037		phy_stackrestore(0x04AA);1038		phy_stackrestore(0x04AC);1039		phy_stackrestore(0x04A0);1040		phy_stackrestore(0x04A7);1041		if (phy->rev >= 2) {1042			phy_stackrestore(0x04C0);1043			phy_stackrestore(0x04C1);1044		} else1045			phy_stackrestore(0x0406);1046		phy_stackrestore(0x04A1);1047		phy_stackrestore(0x04AB);1048		phy_stackrestore(0x04A8);1049		if (phy->rev == 2) {1050			phy_stackrestore(0x04AD);1051			phy_stackrestore(0x04AE);1052		} else if (phy->rev >= 3) {1053			phy_stackrestore(0x04AD);1054			phy_stackrestore(0x0415);1055			phy_stackrestore(0x0416);1056			phy_stackrestore(0x0417);1057			ofdmtab_stackrestore(0x1A00, 0x2);1058			ofdmtab_stackrestore(0x1A00, 0x3);1059		}1060		phy_stackrestore(0x04A2);1061		phy_stackrestore(0x048A);1062		phy_stackrestore(0x042B);1063		phy_stackrestore(0x048C);1064		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW);1065		b43_calc_nrssi_slope(dev);1066		break;1067	default:1068		B43_WARN_ON(1);1069	}1070}1071 1072#undef phy_stacksave1073#undef phy_stackrestore1074#undef radio_stacksave1075#undef radio_stackrestore1076#undef ofdmtab_stacksave1077#undef ofdmtab_stackrestore1078 1079static u16 b43_radio_core_calibration_value(struct b43_wldev *dev)1080{1081	u16 reg, index, ret;1082 1083	static const u8 rcc_table[] = {1084		0x02, 0x03, 0x01, 0x0F,1085		0x06, 0x07, 0x05, 0x0F,1086		0x0A, 0x0B, 0x09, 0x0F,1087		0x0E, 0x0F, 0x0D, 0x0F,1088	};1089 1090	reg = b43_radio_read16(dev, 0x60);1091	index = (reg & 0x001E) >> 1;1092	ret = rcc_table[index] << 1;1093	ret |= (reg & 0x0001);1094	ret |= 0x0020;1095 1096	return ret;1097}1098 1099#define LPD(L, P, D)	(((L) << 2) | ((P) << 1) | ((D) << 0))1100static u16 radio2050_rfover_val(struct b43_wldev *dev,1101				u16 phy_register, unsigned int lpd)1102{1103	struct b43_phy *phy = &dev->phy;1104	struct b43_phy_g *gphy = phy->g;1105	struct ssb_sprom *sprom = dev->dev->bus_sprom;1106 1107	if (!phy->gmode)1108		return 0;1109 1110	if (has_loopback_gain(phy)) {1111		int max_lb_gain = gphy->max_lb_gain;1112		u16 extlna;1113		u16 i;1114 1115		if (phy->radio_rev == 8)1116			max_lb_gain += 0x3E;1117		else1118			max_lb_gain += 0x26;1119		if (max_lb_gain >= 0x46) {1120			extlna = 0x3000;1121			max_lb_gain -= 0x46;1122		} else if (max_lb_gain >= 0x3A) {1123			extlna = 0x1000;1124			max_lb_gain -= 0x3A;1125		} else if (max_lb_gain >= 0x2E) {1126			extlna = 0x2000;1127			max_lb_gain -= 0x2E;1128		} else {1129			extlna = 0;1130			max_lb_gain -= 0x10;1131		}1132 1133		for (i = 0; i < 16; i++) {1134			max_lb_gain -= (i * 6);1135			if (max_lb_gain < 6)1136				break;1137		}1138 1139		if ((phy->rev < 7) ||1140		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {1141			if (phy_register == B43_PHY_RFOVER) {1142				return 0x1B3;1143			} else if (phy_register == B43_PHY_RFOVERVAL) {1144				extlna |= (i << 8);1145				switch (lpd) {1146				case LPD(0, 1, 1):1147					return 0x0F92;1148				case LPD(0, 0, 1):1149				case LPD(1, 0, 1):1150					return (0x0092 | extlna);1151				case LPD(1, 0, 0):1152					return (0x0093 | extlna);1153				}1154				B43_WARN_ON(1);1155			}1156			B43_WARN_ON(1);1157		} else {1158			if (phy_register == B43_PHY_RFOVER) {1159				return 0x9B3;1160			} else if (phy_register == B43_PHY_RFOVERVAL) {1161				if (extlna)1162					extlna |= 0x8000;1163				extlna |= (i << 8);1164				switch (lpd) {1165				case LPD(0, 1, 1):1166					return 0x8F92;1167				case LPD(0, 0, 1):1168					return (0x8092 | extlna);1169				case LPD(1, 0, 1):1170					return (0x2092 | extlna);1171				case LPD(1, 0, 0):1172					return (0x2093 | extlna);1173				}1174				B43_WARN_ON(1);1175			}1176			B43_WARN_ON(1);1177		}1178	} else {1179		if ((phy->rev < 7) ||1180		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {1181			if (phy_register == B43_PHY_RFOVER) {1182				return 0x1B3;1183			} else if (phy_register == B43_PHY_RFOVERVAL) {1184				switch (lpd) {1185				case LPD(0, 1, 1):1186					return 0x0FB2;1187				case LPD(0, 0, 1):1188					return 0x00B2;1189				case LPD(1, 0, 1):1190					return 0x30B2;1191				case LPD(1, 0, 0):1192					return 0x30B3;1193				}1194				B43_WARN_ON(1);1195			}1196			B43_WARN_ON(1);1197		} else {1198			if (phy_register == B43_PHY_RFOVER) {1199				return 0x9B3;1200			} else if (phy_register == B43_PHY_RFOVERVAL) {1201				switch (lpd) {1202				case LPD(0, 1, 1):1203					return 0x8FB2;1204				case LPD(0, 0, 1):1205					return 0x80B2;1206				case LPD(1, 0, 1):1207					return 0x20B2;1208				case LPD(1, 0, 0):1209					return 0x20B3;1210				}1211				B43_WARN_ON(1);1212			}1213			B43_WARN_ON(1);1214		}1215	}1216	return 0;1217}1218 1219struct init2050_saved_values {1220	/* Core registers */1221	u16 reg_3EC;1222	u16 reg_3E6;1223	u16 reg_3F4;1224	/* Radio registers */1225	u16 radio_43;1226	u16 radio_51;1227	u16 radio_52;1228	/* PHY registers */1229	u16 phy_pgactl;1230	u16 phy_cck_5A;1231	u16 phy_cck_59;1232	u16 phy_cck_58;1233	u16 phy_cck_30;1234	u16 phy_rfover;1235	u16 phy_rfoverval;1236	u16 phy_analogover;1237	u16 phy_analogoverval;1238	u16 phy_crs0;1239	u16 phy_classctl;1240	u16 phy_lo_mask;1241	u16 phy_lo_ctl;1242	u16 phy_syncctl;1243};1244 1245static u16 b43_radio_init2050(struct b43_wldev *dev)1246{1247	struct b43_phy *phy = &dev->phy;1248	struct init2050_saved_values sav;1249	u16 rcc;1250	u16 radio78;1251	u16 ret;1252	u16 i, j;1253	u32 tmp1 = 0, tmp2 = 0;1254 1255	memset(&sav, 0, sizeof(sav));	/* get rid of "may be used uninitialized..." */1256 1257	sav.radio_43 = b43_radio_read16(dev, 0x43);1258	sav.radio_51 = b43_radio_read16(dev, 0x51);1259	sav.radio_52 = b43_radio_read16(dev, 0x52);1260	sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);1261	sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A));1262	sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59));1263	sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58));1264 1265	if (phy->type == B43_PHYTYPE_B) {1266		sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30));1267		sav.reg_3EC = b43_read16(dev, 0x3EC);1268 1269		b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF);1270		b43_write16(dev, 0x3EC, 0x3F3F);1271	} else if (phy->gmode || phy->rev >= 2) {1272		sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);1273		sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);1274		sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);1275		sav.phy_analogoverval =1276		    b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);1277		sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);1278		sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);1279 1280		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003);1281		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC);1282		b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF);1283		b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC);1284		if (has_loopback_gain(phy)) {1285			sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);1286			sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL);1287 1288			if (phy->rev >= 3)1289				b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);1290			else1291				b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);1292			b43_phy_write(dev, B43_PHY_LO_CTL, 0);1293		}1294 1295		b43_phy_write(dev, B43_PHY_RFOVERVAL,1296			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,1297						   LPD(0, 1, 1)));1298		b43_phy_write(dev, B43_PHY_RFOVER,1299			      radio2050_rfover_val(dev, B43_PHY_RFOVER, 0));1300	}1301	b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000);1302 1303	sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);1304	b43_phy_mask(dev, B43_PHY_SYNCCTL, 0xFF7F);1305	sav.reg_3E6 = b43_read16(dev, 0x3E6);1306	sav.reg_3F4 = b43_read16(dev, 0x3F4);1307 1308	if (phy->analog == 0) {1309		b43_write16(dev, 0x03E6, 0x0122);1310	} else {1311		if (phy->analog >= 2) {1312			b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFFBF, 0x40);1313		}1314		b43_write16(dev, B43_MMIO_CHANNEL_EXT,1315			    (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000));1316	}1317 1318	rcc = b43_radio_core_calibration_value(dev);1319 1320	if (phy->type == B43_PHYTYPE_B)1321		b43_radio_write16(dev, 0x78, 0x26);1322	if (phy->gmode || phy->rev >= 2) {1323		b43_phy_write(dev, B43_PHY_RFOVERVAL,1324			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,1325						   LPD(0, 1, 1)));1326	}1327	b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF);1328	b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403);1329	if (phy->gmode || phy->rev >= 2) {1330		b43_phy_write(dev, B43_PHY_RFOVERVAL,1331			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,1332						   LPD(0, 0, 1)));1333	}1334	b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0);1335	b43_radio_set(dev, 0x51, 0x0004);1336	if (phy->radio_rev == 8) {1337		b43_radio_write16(dev, 0x43, 0x1F);1338	} else {1339		b43_radio_write16(dev, 0x52, 0);1340		b43_radio_maskset(dev, 0x43, 0xFFF0, 0x0009);1341	}1342	b43_phy_write(dev, B43_PHY_CCK(0x58), 0);1343 1344	for (i = 0; i < 16; i++) {1345		b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480);1346		b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);1347		b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);1348		if (phy->gmode || phy->rev >= 2) {1349			b43_phy_write(dev, B43_PHY_RFOVERVAL,1350				      radio2050_rfover_val(dev,1351							   B43_PHY_RFOVERVAL,1352							   LPD(1, 0, 1)));1353		}1354		b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);1355		udelay(10);1356		if (phy->gmode || phy->rev >= 2) {1357			b43_phy_write(dev, B43_PHY_RFOVERVAL,1358				      radio2050_rfover_val(dev,1359							   B43_PHY_RFOVERVAL,1360							   LPD(1, 0, 1)));1361		}1362		b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);1363		udelay(10);1364		if (phy->gmode || phy->rev >= 2) {1365			b43_phy_write(dev, B43_PHY_RFOVERVAL,1366				      radio2050_rfover_val(dev,1367							   B43_PHY_RFOVERVAL,1368							   LPD(1, 0, 0)));1369		}1370		b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);1371		udelay(20);1372		tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);1373		b43_phy_write(dev, B43_PHY_CCK(0x58), 0);1374		if (phy->gmode || phy->rev >= 2) {1375			b43_phy_write(dev, B43_PHY_RFOVERVAL,1376				      radio2050_rfover_val(dev,1377							   B43_PHY_RFOVERVAL,1378							   LPD(1, 0, 1)));1379		}1380		b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);1381	}1382	udelay(10);1383 1384	b43_phy_write(dev, B43_PHY_CCK(0x58), 0);1385	tmp1++;1386	tmp1 >>= 9;1387 1388	for (i = 0; i < 16; i++) {1389		radio78 = (bitrev4(i) << 1) | 0x0020;1390		b43_radio_write16(dev, 0x78, radio78);1391		udelay(10);1392		for (j = 0; j < 16; j++) {1393			b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80);1394			b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);1395			b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);1396			if (phy->gmode || phy->rev >= 2) {1397				b43_phy_write(dev, B43_PHY_RFOVERVAL,1398					      radio2050_rfover_val(dev,1399								   B43_PHY_RFOVERVAL,1400								   LPD(1, 0,1401								       1)));1402			}1403			b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);1404			udelay(10);1405			if (phy->gmode || phy->rev >= 2) {1406				b43_phy_write(dev, B43_PHY_RFOVERVAL,1407					      radio2050_rfover_val(dev,1408								   B43_PHY_RFOVERVAL,1409								   LPD(1, 0,1410								       1)));1411			}1412			b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);1413			udelay(10);1414			if (phy->gmode || phy->rev >= 2) {1415				b43_phy_write(dev, B43_PHY_RFOVERVAL,1416					      radio2050_rfover_val(dev,1417								   B43_PHY_RFOVERVAL,1418								   LPD(1, 0,1419								       0)));1420			}1421			b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);1422			udelay(10);1423			tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);1424			b43_phy_write(dev, B43_PHY_CCK(0x58), 0);1425			if (phy->gmode || phy->rev >= 2) {1426				b43_phy_write(dev, B43_PHY_RFOVERVAL,1427					      radio2050_rfover_val(dev,1428								   B43_PHY_RFOVERVAL,1429								   LPD(1, 0,1430								       1)));1431			}1432			b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);1433		}1434		tmp2++;1435		tmp2 >>= 8;1436		if (tmp1 < tmp2)1437			break;1438	}1439 1440	/* Restore the registers */1441	b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl);1442	b43_radio_write16(dev, 0x51, sav.radio_51);1443	b43_radio_write16(dev, 0x52, sav.radio_52);1444	b43_radio_write16(dev, 0x43, sav.radio_43);1445	b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A);1446	b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59);1447	b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58);1448	b43_write16(dev, 0x3E6, sav.reg_3E6);1449	if (phy->analog != 0)1450		b43_write16(dev, 0x3F4, sav.reg_3F4);1451	b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl);1452	b43_synth_pu_workaround(dev, phy->channel);1453	if (phy->type == B43_PHYTYPE_B) {1454		b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30);1455		b43_write16(dev, 0x3EC, sav.reg_3EC);1456	} else if (phy->gmode) {1457		b43_write16(dev, B43_MMIO_PHY_RADIO,1458			    b43_read16(dev, B43_MMIO_PHY_RADIO)1459			    & 0x7FFF);1460		b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover);1461		b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval);1462		b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover);1463		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,1464			      sav.phy_analogoverval);1465		b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0);1466		b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl);1467		if (has_loopback_gain(phy)) {1468			b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask);1469			b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl);1470		}1471	}1472	if (i > 15)1473		ret = radio78;1474	else1475		ret = rcc;1476 1477	return ret;1478}1479 1480static void b43_phy_initb5(struct b43_wldev *dev)1481{1482	struct b43_phy *phy = &dev->phy;1483	struct b43_phy_g *gphy = phy->g;1484	u16 offset, value;1485	u8 old_channel;1486 1487	if (phy->analog == 1) {1488		b43_radio_set(dev, 0x007A, 0x0050);1489	}1490	if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&1491	    (dev->dev->board_type != SSB_BOARD_BU4306)) {1492		value = 0x2120;1493		for (offset = 0x00A8; offset < 0x00C7; offset++) {1494			b43_phy_write(dev, offset, value);1495			value += 0x202;1496		}1497	}1498	b43_phy_maskset(dev, 0x0035, 0xF0FF, 0x0700);1499	if (phy->radio_ver == 0x2050)1500		b43_phy_write(dev, 0x0038, 0x0667);1501 1502	if (phy->gmode || phy->rev >= 2) {1503		if (phy->radio_ver == 0x2050) {1504			b43_radio_set(dev, 0x007A, 0x0020);1505			b43_radio_set(dev, 0x0051, 0x0004);1506		}1507		b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000);1508 1509		b43_phy_set(dev, 0x0802, 0x0100);1510		b43_phy_set(dev, 0x042B, 0x2000);1511 1512		b43_phy_write(dev, 0x001C, 0x186A);1513 1514		b43_phy_maskset(dev, 0x0013, 0x00FF, 0x1900);1515		b43_phy_maskset(dev, 0x0035, 0xFFC0, 0x0064);1516		b43_phy_maskset(dev, 0x005D, 0xFF80, 0x000A);1517	}1518 1519	if (dev->bad_frames_preempt) {1520		b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, (1 << 11));1521	}1522 1523	if (phy->analog == 1) {1524		b43_phy_write(dev, 0x0026, 0xCE00);1525		b43_phy_write(dev, 0x0021, 0x3763);1526		b43_phy_write(dev, 0x0022, 0x1BC3);1527		b43_phy_write(dev, 0x0023, 0x06F9);1528		b43_phy_write(dev, 0x0024, 0x037E);1529	} else1530		b43_phy_write(dev, 0x0026, 0xCC00);1531	b43_phy_write(dev, 0x0030, 0x00C6);1532	b43_write16(dev, 0x03EC, 0x3F22);1533 1534	if (phy->analog == 1)1535		b43_phy_write(dev, 0x0020, 0x3E1C);1536	else1537		b43_phy_write(dev, 0x0020, 0x301C);1538 1539	if (phy->analog == 0)1540		b43_write16(dev, 0x03E4, 0x3000);1541 1542	old_channel = phy->channel;1543	/* Force to channel 7, even if not supported. */1544	b43_gphy_channel_switch(dev, 7, 0);1545 1546	if (phy->radio_ver != 0x2050) {1547		b43_radio_write16(dev, 0x0075, 0x0080);1548		b43_radio_write16(dev, 0x0079, 0x0081);1549	}1550 1551	b43_radio_write16(dev, 0x0050, 0x0020);1552	b43_radio_write16(dev, 0x0050, 0x0023);1553 1554	if (phy->radio_ver == 0x2050) {1555		b43_radio_write16(dev, 0x0050, 0x0020);1556		b43_radio_write16(dev, 0x005A, 0x0070);1557	}1558 1559	b43_radio_write16(dev, 0x005B, 0x007B);1560	b43_radio_write16(dev, 0x005C, 0x00B0);1561 1562	b43_radio_set(dev, 0x007A, 0x0007);1563 1564	b43_gphy_channel_switch(dev, old_channel, 0);1565 1566	b43_phy_write(dev, 0x0014, 0x0080);1567	b43_phy_write(dev, 0x0032, 0x00CA);1568	b43_phy_write(dev, 0x002A, 0x88A3);1569 1570	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);1571 1572	if (phy->radio_ver == 0x2050)1573		b43_radio_write16(dev, 0x005D, 0x000D);1574 1575	b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);1576}1577 1578/* https://bcm-v4.sipsolutions.net/802.11/PHY/Init/B6 */1579static void b43_phy_initb6(struct b43_wldev *dev)1580{1581	struct b43_phy *phy = &dev->phy;1582	struct b43_phy_g *gphy = phy->g;1583	u16 offset, val;1584	u8 old_channel;1585 1586	b43_phy_write(dev, 0x003E, 0x817A);1587	b43_radio_write16(dev, 0x007A,1588			  (b43_radio_read16(dev, 0x007A) | 0x0058));1589	if (phy->radio_rev == 4 || phy->radio_rev == 5) {1590		b43_radio_write16(dev, 0x51, 0x37);1591		b43_radio_write16(dev, 0x52, 0x70);1592		b43_radio_write16(dev, 0x53, 0xB3);1593		b43_radio_write16(dev, 0x54, 0x9B);1594		b43_radio_write16(dev, 0x5A, 0x88);1595		b43_radio_write16(dev, 0x5B, 0x88);1596		b43_radio_write16(dev, 0x5D, 0x88);1597		b43_radio_write16(dev, 0x5E, 0x88);1598		b43_radio_write16(dev, 0x7D, 0x88);1599		b43_hf_write(dev, b43_hf_read(dev)1600			     | B43_HF_TSSIRPSMW);1601	}1602	B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7);	/* We had code for these revs here... */1603	if (phy->radio_rev == 8) {1604		b43_radio_write16(dev, 0x51, 0);1605		b43_radio_write16(dev, 0x52, 0x40);1606		b43_radio_write16(dev, 0x53, 0xB7);1607		b43_radio_write16(dev, 0x54, 0x98);1608		b43_radio_write16(dev, 0x5A, 0x88);1609		b43_radio_write16(dev, 0x5B, 0x6B);1610		b43_radio_write16(dev, 0x5C, 0x0F);1611		if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {1612			b43_radio_write16(dev, 0x5D, 0xFA);1613			b43_radio_write16(dev, 0x5E, 0xD8);1614		} else {1615			b43_radio_write16(dev, 0x5D, 0xF5);1616			b43_radio_write16(dev, 0x5E, 0xB8);1617		}1618		b43_radio_write16(dev, 0x0073, 0x0003);1619		b43_radio_write16(dev, 0x007D, 0x00A8);1620		b43_radio_write16(dev, 0x007C, 0x0001);1621		b43_radio_write16(dev, 0x007E, 0x0008);1622	}1623	val = 0x1E1F;1624	for (offset = 0x0088; offset < 0x0098; offset++) {1625		b43_phy_write(dev, offset, val);1626		val -= 0x0202;1627	}1628	val = 0x3E3F;1629	for (offset = 0x0098; offset < 0x00A8; offset++) {1630		b43_phy_write(dev, offset, val);1631		val -= 0x0202;1632	}1633	val = 0x2120;1634	for (offset = 0x00A8; offset < 0x00C8; offset++) {1635		b43_phy_write(dev, offset, (val & 0x3F3F));1636		val += 0x0202;1637	}1638	if (phy->type == B43_PHYTYPE_G) {1639		b43_radio_set(dev, 0x007A, 0x0020);1640		b43_radio_set(dev, 0x0051, 0x0004);1641		b43_phy_set(dev, 0x0802, 0x0100);1642		b43_phy_set(dev, 0x042B, 0x2000);1643		b43_phy_write(dev, 0x5B, 0);1644		b43_phy_write(dev, 0x5C, 0);1645	}1646 1647	old_channel = phy->channel;1648	if (old_channel >= 8)1649		b43_gphy_channel_switch(dev, 1, 0);1650	else1651		b43_gphy_channel_switch(dev, 13, 0);1652 1653	b43_radio_write16(dev, 0x0050, 0x0020);1654	b43_radio_write16(dev, 0x0050, 0x0023);1655	udelay(40);1656	if (phy->radio_rev < 6 || phy->radio_rev == 8) {1657		b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C)1658					      | 0x0002));1659		b43_radio_write16(dev, 0x50, 0x20);1660	}1661	if (phy->radio_rev <= 2) {1662		b43_radio_write16(dev, 0x50, 0x20);1663		b43_radio_write16(dev, 0x5A, 0x70);1664		b43_radio_write16(dev, 0x5B, 0x7B);1665		b43_radio_write16(dev, 0x5C, 0xB0);1666	}1667	b43_radio_maskset(dev, 0x007A, 0x00F8, 0x0007);1668 1669	b43_gphy_channel_switch(dev, old_channel, 0);1670 1671	b43_phy_write(dev, 0x0014, 0x0200);1672	if (phy->radio_rev >= 6)1673		b43_phy_write(dev, 0x2A, 0x88C2);1674	else1675		b43_phy_write(dev, 0x2A, 0x8AC0);1676	b43_phy_write(dev, 0x0038, 0x0668);1677	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);1678	if (phy->radio_rev == 4 || phy->radio_rev == 5)1679		b43_phy_maskset(dev, 0x5D, 0xFF80, 0x0003);1680	if (phy->radio_rev <= 2)1681		b43_radio_write16(dev, 0x005D, 0x000D);1682 1683	if (phy->analog == 4) {1684		b43_write16(dev, 0x3E4, 9);1685		b43_phy_mask(dev, 0x61, 0x0FFF);1686	} else {1687		b43_phy_maskset(dev, 0x0002, 0xFFC0, 0x0004);1688	}1689	if (phy->type == B43_PHYTYPE_B)1690		B43_WARN_ON(1);1691	else if (phy->type == B43_PHYTYPE_G)1692		b43_write16(dev, 0x03E6, 0x0);1693}1694 1695static void b43_calc_loopback_gain(struct b43_wldev *dev)1696{1697	struct b43_phy *phy = &dev->phy;1698	struct b43_phy_g *gphy = phy->g;1699	u16 backup_phy[16] = { 0 };1700	u16 backup_radio[3];1701	u16 backup_bband;1702	u16 i, j, loop_i_max;1703	u16 trsw_rx;1704	u16 loop1_outer_done, loop1_inner_done;1705 1706	backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0);1707	backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);1708	backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER);1709	backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL);1710	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */1711		backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);1712		backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);1713	}1714	backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A));1715	backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59));1716	backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58));1717	backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A));1718	backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03));1719	backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);1720	backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);1721	backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B));1722	backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);1723	backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);1724	backup_bband = gphy->bbatt.att;1725	backup_radio[0] = b43_radio_read16(dev, 0x52);1726	backup_radio[1] = b43_radio_read16(dev, 0x43);1727	backup_radio[2] = b43_radio_read16(dev, 0x7A);1728 1729	b43_phy_mask(dev, B43_PHY_CRS0, 0x3FFF);1730	b43_phy_set(dev, B43_PHY_CCKBBANDCFG, 0x8000);1731	b43_phy_set(dev, B43_PHY_RFOVER, 0x0002);1732	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFD);1733	b43_phy_set(dev, B43_PHY_RFOVER, 0x0001);1734	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFE);1735	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */1736		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0001);1737		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFE);1738		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0002);1739		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFD);1740	}1741	b43_phy_set(dev, B43_PHY_RFOVER, 0x000C);1742	b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x000C);1743	b43_phy_set(dev, B43_PHY_RFOVER, 0x0030);1744	b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xFFCF, 0x10);1745 1746	b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780);1747	b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);1748	b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);1749 1750	b43_phy_set(dev, B43_PHY_CCK(0x0A), 0x2000);1751	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */1752		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0004);1753		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFB);1754	}1755	b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFF9F, 0x40);1756 1757	if (phy->radio_rev == 8) {1758		b43_radio_write16(dev, 0x43, 0x000F);1759	} else {1760		b43_radio_write16(dev, 0x52, 0);1761		b43_radio_maskset(dev, 0x43, 0xFFF0, 0x9);1762	}1763	b43_gphy_set_baseband_attenuation(dev, 11);1764 1765	if (phy->rev >= 3)1766		b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);1767	else1768		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);1769	b43_phy_write(dev, B43_PHY_LO_CTL, 0);1770 1771	b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xFFC0, 0x01);1772	b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xC0FF, 0x800);1773 1774	b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);1775	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);1776 1777	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {1778		if (phy->rev >= 7) {1779			b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);1780			b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);1781		}1782	}1783	b43_radio_mask(dev, 0x7A, 0x00F7);1784 1785	j = 0;1786	loop_i_max = (phy->radio_rev == 8) ? 15 : 9;1787	for (i = 0; i < loop_i_max; i++) {1788		for (j = 0; j < 16; j++) {1789			b43_radio_write16(dev, 0x43, i);1790			b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8));1791			b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000);1792			b43_phy_set(dev, B43_PHY_PGACTL, 0xF000);1793			udelay(20);1794			if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)1795				goto exit_loop1;1796		}1797	}1798      exit_loop1:1799	loop1_outer_done = i;1800	loop1_inner_done = j;1801	if (j >= 8) {1802		b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x30);1803		trsw_rx = 0x1B;1804		for (j = j - 8; j < 16; j++) {1805			b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8));1806			b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000);1807			b43_phy_set(dev, B43_PHY_PGACTL, 0xF000);1808			udelay(20);1809			trsw_rx -= 3;1810			if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)1811				goto exit_loop2;1812		}1813	} else1814		trsw_rx = 0x18;1815      exit_loop2:1816 1817	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */1818		b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);1819		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);1820	}1821	b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]);1822	b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]);1823	b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]);1824	b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]);1825	b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]);1826	b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);1827	b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);1828	b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]);1829	b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);1830 1831	b43_gphy_set_baseband_attenuation(dev, backup_bband);1832 1833	b43_radio_write16(dev, 0x52, backup_radio[0]);1834	b43_radio_write16(dev, 0x43, backup_radio[1]);1835	b43_radio_write16(dev, 0x7A, backup_radio[2]);1836 1837	b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003);1838	udelay(10);1839	b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]);1840	b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]);1841	b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]);1842	b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]);1843 1844	gphy->max_lb_gain =1845	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;1846	gphy->trsw_rx_gain = trsw_rx * 2;1847}1848 1849static void b43_hardware_pctl_early_init(struct b43_wldev *dev)1850{1851	struct b43_phy *phy = &dev->phy;1852 1853	if (!b43_has_hardware_pctl(dev)) {1854		b43_phy_write(dev, 0x047A, 0xC111);1855		return;1856	}1857 1858	b43_phy_mask(dev, 0x0036, 0xFEFF);1859	b43_phy_write(dev, 0x002F, 0x0202);1860	b43_phy_set(dev, 0x047C, 0x0002);1861	b43_phy_set(dev, 0x047A, 0xF000);1862	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {1863		b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010);1864		b43_phy_set(dev, 0x005D, 0x8000);1865		b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010);1866		b43_phy_write(dev, 0x002E, 0xC07F);1867		b43_phy_set(dev, 0x0036, 0x0400);1868	} else {1869		b43_phy_set(dev, 0x0036, 0x0200);1870		b43_phy_set(dev, 0x0036, 0x0400);1871		b43_phy_mask(dev, 0x005D, 0x7FFF);1872		b43_phy_mask(dev, 0x004F, 0xFFFE);1873		b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010);1874		b43_phy_write(dev, 0x002E, 0xC07F);1875		b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010);1876	}1877}1878 1879/* Hardware power control for G-PHY */1880static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)1881{1882	struct b43_phy *phy = &dev->phy;1883	struct b43_phy_g *gphy = phy->g;1884 1885	if (!b43_has_hardware_pctl(dev)) {1886		/* No hardware power control */1887		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL);1888		return;1889	}1890 1891	b43_phy_maskset(dev, 0x0036, 0xFFC0, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));1892	b43_phy_maskset(dev, 0x0478, 0xFF00, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));1893	b43_gphy_tssi_power_lt_init(dev);1894	b43_gphy_gain_lt_init(dev);1895	b43_phy_mask(dev, 0x0060, 0xFFBF);1896	b43_phy_write(dev, 0x0014, 0x0000);1897 1898	B43_WARN_ON(phy->rev < 6);1899	b43_phy_set(dev, 0x0478, 0x0800);1900	b43_phy_mask(dev, 0x0478, 0xFEFF);1901	b43_phy_mask(dev, 0x0801, 0xFFBF);1902 1903	b43_gphy_dc_lt_init(dev, 1);1904 1905	/* Enable hardware pctl in firmware. */1906	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);1907}1908 1909/* Initialize B/G PHY power control */1910static void b43_phy_init_pctl(struct b43_wldev *dev)1911{1912	struct b43_phy *phy = &dev->phy;1913	struct b43_phy_g *gphy = phy->g;1914	struct b43_rfatt old_rfatt;1915	struct b43_bbatt old_bbatt;1916	u8 old_tx_control = 0;1917 1918	B43_WARN_ON(phy->type != B43_PHYTYPE_G);1919 1920	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&1921	    (dev->dev->board_type == SSB_BOARD_BU4306))1922		return;1923 1924	b43_phy_write(dev, 0x0028, 0x8018);1925 1926	/* This does something with the Analog... */1927	b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0)1928		    & 0xFFDF);1929 1930	if (!phy->gmode)1931		return;1932	b43_hardware_pctl_early_init(dev);1933	if (gphy->cur_idle_tssi == 0) {1934		if (phy->radio_ver == 0x2050 && phy->analog == 0) {1935			b43_radio_maskset(dev, 0x0076, 0x00F7, 0x0084);1936		} else {1937			struct b43_rfatt rfatt;1938			struct b43_bbatt bbatt;1939 1940			memcpy(&old_rfatt, &gphy->rfatt, sizeof(old_rfatt));1941			memcpy(&old_bbatt, &gphy->bbatt, sizeof(old_bbatt));1942			old_tx_control = gphy->tx_control;1943 1944			bbatt.att = 11;1945			if (phy->radio_rev == 8) {1946				rfatt.att = 15;1947				rfatt.with_padmix = true;1948			} else {1949				rfatt.att = 9;1950				rfatt.with_padmix = false;1951			}1952			b43_set_txpower_g(dev, &bbatt, &rfatt, 0);1953		}1954		b43_dummy_transmission(dev, false, true);1955		gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);1956		if (B43_DEBUG) {1957			/* Current-Idle-TSSI sanity check. */1958			if (abs(gphy->cur_idle_tssi - gphy->tgt_idle_tssi) >= 20) {1959				b43dbg(dev->wl,1960				       "!WARNING! Idle-TSSI phy->cur_idle_tssi "1961				       "measuring failed. (cur=%d, tgt=%d). Disabling TX power "1962				       "adjustment.\n", gphy->cur_idle_tssi,1963				       gphy->tgt_idle_tssi);1964				gphy->cur_idle_tssi = 0;1965			}1966		}1967		if (phy->radio_ver == 0x2050 && phy->analog == 0) {1968			b43_radio_mask(dev, 0x0076, 0xFF7B);1969		} else {1970			b43_set_txpower_g(dev, &old_bbatt,1971					  &old_rfatt, old_tx_control);1972		}1973	}1974	b43_hardware_pctl_init_gphy(dev);1975	b43_shm_clear_tssi(dev);1976}1977 1978static void b43_phy_inita(struct b43_wldev *dev)1979{1980	struct b43_phy *phy = &dev->phy;1981 1982	might_sleep();1983 1984	if (phy->rev >= 6) {1985		if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)1986			b43_phy_set(dev, B43_PHY_ENCORE, 0x0010);1987		else1988			b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010);1989	}1990 1991	b43_wa_all(dev);1992 1993	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)1994		b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);1995}1996 1997static void b43_phy_initg(struct b43_wldev *dev)1998{1999	struct b43_phy *phy = &dev->phy;2000	struct b43_phy_g *gphy = phy->g;2001	u16 tmp;2002 2003	if (phy->rev == 1)2004		b43_phy_initb5(dev);2005	else2006		b43_phy_initb6(dev);2007 2008	if (phy->rev >= 2 || phy->gmode)2009		b43_phy_inita(dev);2010 2011	if (phy->rev >= 2) {2012		b43_phy_write(dev, B43_PHY_ANALOGOVER, 0);2013		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0);2014	}2015	if (phy->rev == 2) {2016		b43_phy_write(dev, B43_PHY_RFOVER, 0);2017		b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);2018	}2019	if (phy->rev > 5) {2020		b43_phy_write(dev, B43_PHY_RFOVER, 0x400);2021		b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);2022	}2023	if (phy->gmode || phy->rev >= 2) {2024		tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM);2025		tmp &= B43_PHYVER_VERSION;2026		if (tmp == 3 || tmp == 5) {2027			b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816);2028			b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006);2029		}2030		if (tmp == 5) {2031			b43_phy_maskset(dev, B43_PHY_OFDM(0xCC), 0x00FF, 0x1F00);2032		}2033	}2034	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)2035		b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78);2036	if (phy->radio_rev == 8) {2037		b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x80);2038		b43_phy_set(dev, B43_PHY_OFDM(0x3E), 0x4);2039	}2040	if (has_loopback_gain(phy))2041		b43_calc_loopback_gain(dev);2042 2043	if (phy->radio_rev != 8) {2044		if (gphy->initval == 0xFFFF)2045			gphy->initval = b43_radio_init2050(dev);2046		else2047			b43_radio_write16(dev, 0x0078, gphy->initval);2048	}2049	b43_lo_g_init(dev);2050	if (has_tx_magnification(phy)) {2051		b43_radio_write16(dev, 0x52,2052				  (b43_radio_read16(dev, 0x52) & 0xFF00)2053				  | gphy->lo_control->tx_bias | gphy->2054				  lo_control->tx_magn);2055	} else {2056		b43_radio_maskset(dev, 0x52, 0xFFF0, gphy->lo_control->tx_bias);2057	}2058	if (phy->rev >= 6) {2059		b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));2060	}2061	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)2062		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);2063	else2064		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);2065	if (phy->rev < 2)2066		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);2067	else2068		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);2069	if (phy->gmode || phy->rev >= 2) {2070		b43_lo_g_adjust(dev);2071		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);2072	}2073 2074	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {2075		/* The specs state to update the NRSSI LT with2076		 * the value 0x7FFFFFFF here. I think that is some weird2077		 * compiler optimization in the original driver.2078		 * Essentially, what we do here is resetting all NRSSI LT2079		 * entries to -32 (see the clamp_val() in nrssi_hw_update())2080		 */2081		b43_nrssi_hw_update(dev, 0xFFFF);	//FIXME?2082		b43_calc_nrssi_threshold(dev);2083	} else if (phy->gmode || phy->rev >= 2) {2084		if (gphy->nrssi[0] == -1000) {2085			B43_WARN_ON(gphy->nrssi[1] != -1000);2086			b43_calc_nrssi_slope(dev);2087		} else2088			b43_calc_nrssi_threshold(dev);2089	}2090	if (phy->radio_rev == 8)2091		b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230);2092	b43_phy_init_pctl(dev);2093	/* FIXME: The spec says in the following if, the 0 should be replaced2094	   'if OFDM may not be used in the current locale'2095	   but OFDM is legal everywhere */2096	if ((dev->dev->chip_id == 0x43062097	     && dev->dev->chip_pkg == 2) || 0) {2098		b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);2099		b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);2100	}2101}2102 2103void b43_gphy_channel_switch(struct b43_wldev *dev,2104			     unsigned int channel,2105			     bool synthetic_pu_workaround)2106{2107	if (synthetic_pu_workaround)2108		b43_synth_pu_workaround(dev, channel);2109 2110	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));2111 2112	if (channel == 14) {2113		if (dev->dev->bus_sprom->country_code ==2114		    SSB_SPROM1CCODE_JAPAN)2115			b43_hf_write(dev,2116				     b43_hf_read(dev) & ~B43_HF_ACPR);2117		else2118			b43_hf_write(dev,2119				     b43_hf_read(dev) | B43_HF_ACPR);2120		b43_write16(dev, B43_MMIO_CHANNEL_EXT,2121			    b43_read16(dev, B43_MMIO_CHANNEL_EXT)2122			    | (1 << 11));2123	} else {2124		b43_write16(dev, B43_MMIO_CHANNEL_EXT,2125			    b43_read16(dev, B43_MMIO_CHANNEL_EXT)2126			    & 0xF7BF);2127	}2128}2129 2130static void default_baseband_attenuation(struct b43_wldev *dev,2131					 struct b43_bbatt *bb)2132{2133	struct b43_phy *phy = &dev->phy;2134 2135	if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)2136		bb->att = 0;2137	else2138		bb->att = 2;2139}2140 2141static void default_radio_attenuation(struct b43_wldev *dev,2142				      struct b43_rfatt *rf)2143{2144	struct b43_bus_dev *bdev = dev->dev;2145	struct b43_phy *phy = &dev->phy;2146 2147	rf->with_padmix = false;2148 2149	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&2150	    dev->dev->board_type == SSB_BOARD_BCM4309G) {2151		if (dev->dev->board_rev < 0x43) {2152			rf->att = 2;2153			return;2154		} else if (dev->dev->board_rev < 0x51) {2155			rf->att = 3;2156			return;2157		}2158	}2159 2160	switch (phy->radio_ver) {2161	case 0x2053:2162		switch (phy->radio_rev) {2163		case 1:2164			rf->att = 6;2165			return;2166		}2167		break;2168	case 0x2050:2169		switch (phy->radio_rev) {2170		case 0:2171			rf->att = 5;2172			return;2173		case 1:2174			if (phy->type == B43_PHYTYPE_G) {2175				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM2176				    && bdev->board_type == SSB_BOARD_BCM4309G2177				    && bdev->board_rev >= 30)2178					rf->att = 3;2179				else if (bdev->board_vendor ==2180					 SSB_BOARDVENDOR_BCM2181					 && bdev->board_type ==2182					 SSB_BOARD_BU4306)2183					rf->att = 3;2184				else2185					rf->att = 1;2186			} else {2187				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM2188				    && bdev->board_type == SSB_BOARD_BCM4309G2189				    && bdev->board_rev >= 30)2190					rf->att = 7;2191				else2192					rf->att = 6;2193			}2194			return;2195		case 2:2196			if (phy->type == B43_PHYTYPE_G) {2197				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM2198				    && bdev->board_type == SSB_BOARD_BCM4309G2199				    && bdev->board_rev >= 30)2200					rf->att = 3;2201				else if (bdev->board_vendor ==2202					 SSB_BOARDVENDOR_BCM2203					 && bdev->board_type ==2204					 SSB_BOARD_BU4306)2205					rf->att = 5;2206				else if (bdev->chip_id == 0x4320)2207					rf->att = 4;2208				else2209					rf->att = 3;2210			} else2211				rf->att = 6;2212			return;2213		case 3:2214			rf->att = 5;2215			return;2216		case 4:2217		case 5:2218			rf->att = 1;2219			return;2220		case 6:2221		case 7:2222			rf->att = 5;2223			return;2224		case 8:2225			rf->att = 0xA;2226			rf->with_padmix = true;2227			return;2228		case 9:2229		default:2230			rf->att = 5;2231			return;2232		}2233	}2234	rf->att = 5;2235}2236 2237static u16 default_tx_control(struct b43_wldev *dev)2238{2239	struct b43_phy *phy = &dev->phy;2240 2241	if (phy->radio_ver != 0x2050)2242		return 0;2243	if (phy->radio_rev == 1)2244		return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX;2245	if (phy->radio_rev < 6)2246		return B43_TXCTL_PA2DB;2247	if (phy->radio_rev == 8)2248		return B43_TXCTL_TXMIX;2249	return 0;2250}2251 2252static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel)2253{2254	struct b43_phy *phy = &dev->phy;2255	struct b43_phy_g *gphy = phy->g;2256	u8 ret = 0;2257	u16 saved, rssi, temp;2258	int i, j = 0;2259 2260	saved = b43_phy_read(dev, 0x0403);2261	b43_switch_channel(dev, channel);2262	b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);2263	if (gphy->aci_hw_rssi)2264		rssi = b43_phy_read(dev, 0x048A) & 0x3F;2265	else2266		rssi = saved & 0x3F;2267	/* clamp temp to signed 5bit */2268	if (rssi > 32)2269		rssi -= 64;2270	for (i = 0; i < 100; i++) {2271		temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F;2272		if (temp > 32)2273			temp -= 64;2274		if (temp < rssi)2275			j++;2276		if (j >= 20)2277			ret = 1;2278	}2279	b43_phy_write(dev, 0x0403, saved);2280 2281	return ret;2282}2283 2284static u8 b43_gphy_aci_scan(struct b43_wldev *dev)2285{2286	struct b43_phy *phy = &dev->phy;2287	u8 ret[13] = { 0 };2288	unsigned int channel = phy->channel;2289	unsigned int i, j, start, end;2290 2291	if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))2292		return 0;2293 2294	b43_phy_lock(dev);2295	b43_radio_lock(dev);2296	b43_phy_mask(dev, 0x0802, 0xFFFC);2297	b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);2298	b43_set_all_gains(dev, 3, 8, 1);2299 2300	start = (channel > 5) ? channel - 5 : 1;2301	end = (channel + 5 < 14) ? channel + 5 : 13;2302 2303	for (i = start; i <= end; i++) {2304		if (abs(channel - i) > 2)2305			ret[i - 1] = b43_gphy_aci_detect(dev, i);2306	}2307	b43_switch_channel(dev, channel);2308	b43_phy_maskset(dev, 0x0802, 0xFFFC, 0x0003);2309	b43_phy_mask(dev, 0x0403, 0xFFF8);2310	b43_phy_set(dev, B43_PHY_G_CRS, 0x8000);2311	b43_set_original_gains(dev);2312	for (i = 0; i < 13; i++) {2313		if (!ret[i])2314			continue;2315		end = (i + 5 < 13) ? i + 5 : 13;2316		for (j = i; j < end; j++)2317			ret[j] = 1;2318	}2319	b43_radio_unlock(dev);2320	b43_phy_unlock(dev);2321 2322	return ret[channel - 1];2323}2324 2325static s32 b43_tssi2dbm_ad(s32 num, s32 den)2326{2327	if (num < 0)2328		return num / den;2329	else2330		return (num + den / 2) / den;2331}2332 2333static s8 b43_tssi2dbm_entry(s8 entry[], u8 index,2334			     s16 pab0, s16 pab1, s16 pab2)2335{2336	s32 m1, m2, f = 256, q, delta;2337	s8 i = 0;2338 2339	m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32);2340	m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1);2341	do {2342		if (i > 15)2343			return -EINVAL;2344		q = b43_tssi2dbm_ad(f * 4096 -2345				    b43_tssi2dbm_ad(m2 * f, 16) * f, 2048);2346		delta = abs(q - f);2347		f = q;2348		i++;2349	} while (delta >= 2);2350	entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);2351	return 0;2352}2353 2354u8 *b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,2355				  s16 pab0, s16 pab1, s16 pab2)2356{2357	unsigned int i;2358	u8 *tab;2359	int err;2360 2361	tab = kmalloc(64, GFP_KERNEL);2362	if (!tab) {2363		b43err(dev->wl, "Could not allocate memory "2364		       "for tssi2dbm table\n");2365		return NULL;2366	}2367	for (i = 0; i < 64; i++) {2368		err = b43_tssi2dbm_entry(tab, i, pab0, pab1, pab2);2369		if (err) {2370			b43err(dev->wl, "Could not generate "2371			       "tssi2dBm table\n");2372			kfree(tab);2373			return NULL;2374		}2375	}2376 2377	return tab;2378}2379 2380/* Initialise the TSSI->dBm lookup table */2381static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)2382{2383	struct b43_phy *phy = &dev->phy;2384	struct b43_phy_g *gphy = phy->g;2385	s16 pab0, pab1, pab2;2386 2387	pab0 = (s16) (dev->dev->bus_sprom->pa0b0);2388	pab1 = (s16) (dev->dev->bus_sprom->pa0b1);2389	pab2 = (s16) (dev->dev->bus_sprom->pa0b2);2390 2391	B43_WARN_ON((dev->dev->chip_id == 0x4301) &&2392		    (phy->radio_ver != 0x2050)); /* Not supported anymore */2393 2394	gphy->dyn_tssi_tbl = false;2395 2396	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&2397	    pab0 != -1 && pab1 != -1 && pab2 != -1) {2398		/* The pabX values are set in SPROM. Use them. */2399		if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&2400		    (s8) dev->dev->bus_sprom->itssi_bg != -1) {2401			gphy->tgt_idle_tssi =2402				(s8) (dev->dev->bus_sprom->itssi_bg);2403		} else2404			gphy->tgt_idle_tssi = 62;2405		gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,2406							       pab1, pab2);2407		if (!gphy->tssi2dbm)2408			return -ENOMEM;2409		gphy->dyn_tssi_tbl = true;2410	} else {2411		/* pabX values not set in SPROM. */2412		gphy->tgt_idle_tssi = 52;2413		gphy->tssi2dbm = b43_tssi2dbm_g_table;2414	}2415 2416	return 0;2417}2418 2419static int b43_gphy_op_allocate(struct b43_wldev *dev)2420{2421	struct b43_phy_g *gphy;2422	struct b43_txpower_lo_control *lo;2423	int err;2424 2425	gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);2426	if (!gphy) {2427		err = -ENOMEM;2428		goto error;2429	}2430	dev->phy.g = gphy;2431 2432	lo = kzalloc(sizeof(*lo), GFP_KERNEL);2433	if (!lo) {2434		err = -ENOMEM;2435		goto err_free_gphy;2436	}2437	gphy->lo_control = lo;2438 2439	err = b43_gphy_init_tssi2dbm_table(dev);2440	if (err)2441		goto err_free_lo;2442 2443	return 0;2444 2445err_free_lo:2446	kfree(lo);2447err_free_gphy:2448	kfree(gphy);2449error:2450	return err;2451}2452 2453static void b43_gphy_op_prepare_structs(struct b43_wldev *dev)2454{2455	struct b43_phy *phy = &dev->phy;2456	struct b43_phy_g *gphy = phy->g;2457	const void *tssi2dbm;2458	int tgt_idle_tssi;2459	struct b43_txpower_lo_control *lo;2460	unsigned int i;2461 2462	/* tssi2dbm table is constant, so it is initialized at alloc time.2463	 * Save a copy of the pointer. */2464	tssi2dbm = gphy->tssi2dbm;2465	tgt_idle_tssi = gphy->tgt_idle_tssi;2466	/* Save the LO pointer. */2467	lo = gphy->lo_control;2468 2469	/* Zero out the whole PHY structure. */2470	memset(gphy, 0, sizeof(*gphy));2471 2472	/* Restore pointers. */2473	gphy->tssi2dbm = tssi2dbm;2474	gphy->tgt_idle_tssi = tgt_idle_tssi;2475	gphy->lo_control = lo;2476 2477	memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig));2478 2479	/* NRSSI */2480	for (i = 0; i < ARRAY_SIZE(gphy->nrssi); i++)2481		gphy->nrssi[i] = -1000;2482	for (i = 0; i < ARRAY_SIZE(gphy->nrssi_lt); i++)2483		gphy->nrssi_lt[i] = i;2484 2485	gphy->lofcal = 0xFFFF;2486	gphy->initval = 0xFFFF;2487 2488	gphy->interfmode = B43_INTERFMODE_NONE;2489 2490	/* OFDM-table address caching. */2491	gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;2492 2493	gphy->average_tssi = 0xFF;2494 2495	/* Local Osciallator structure */2496	lo->tx_bias = 0xFF;2497	INIT_LIST_HEAD(&lo->calib_list);2498}2499 2500static void b43_gphy_op_free(struct b43_wldev *dev)2501{2502	struct b43_phy *phy = &dev->phy;2503	struct b43_phy_g *gphy = phy->g;2504 2505	kfree(gphy->lo_control);2506 2507	if (gphy->dyn_tssi_tbl)2508		kfree(gphy->tssi2dbm);2509	gphy->dyn_tssi_tbl = false;2510	gphy->tssi2dbm = NULL;2511 2512	kfree(gphy);2513	dev->phy.g = NULL;2514}2515 2516static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)2517{2518	struct b43_phy *phy = &dev->phy;2519	struct b43_phy_g *gphy = phy->g;2520	struct b43_txpower_lo_control *lo = gphy->lo_control;2521 2522	B43_WARN_ON(phy->type != B43_PHYTYPE_G);2523 2524	default_baseband_attenuation(dev, &gphy->bbatt);2525	default_radio_attenuation(dev, &gphy->rfatt);2526	gphy->tx_control = (default_tx_control(dev) << 4);2527	generate_rfatt_list(dev, &lo->rfatt_list);2528	generate_bbatt_list(dev, &lo->bbatt_list);2529 2530	/* Commit previous writes */2531	b43_read32(dev, B43_MMIO_MACCTL);2532 2533	if (phy->rev == 1) {2534		/* Workaround: Temporarly disable gmode through the early init2535		 * phase, as the gmode stuff is not needed for phy rev 1 */2536		phy->gmode = false;2537		b43_wireless_core_reset(dev, 0);2538		b43_phy_initg(dev);2539		phy->gmode = true;2540		b43_wireless_core_reset(dev, 1);2541	}2542 2543	return 0;2544}2545 2546static int b43_gphy_op_init(struct b43_wldev *dev)2547{2548	b43_phy_initg(dev);2549 2550	return 0;2551}2552 2553static void b43_gphy_op_exit(struct b43_wldev *dev)2554{2555	b43_lo_g_cleanup(dev);2556}2557 2558static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)2559{2560	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);2561	return b43_read16(dev, B43_MMIO_PHY_DATA);2562}2563 2564static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)2565{2566	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);2567	b43_write16(dev, B43_MMIO_PHY_DATA, value);2568}2569 2570static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg)2571{2572	/* Register 1 is a 32-bit register. */2573	B43_WARN_ON(reg == 1);2574	/* G-PHY needs 0x80 for read access. */2575	reg |= 0x80;2576 2577	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);2578	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);2579}2580 2581static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)2582{2583	/* Register 1 is a 32-bit register. */2584	B43_WARN_ON(reg == 1);2585 2586	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);2587	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);2588}2589 2590static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev)2591{2592	return (dev->phy.rev >= 6);2593}2594 2595static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,2596					bool blocked)2597{2598	struct b43_phy *phy = &dev->phy;2599	struct b43_phy_g *gphy = phy->g;2600	unsigned int channel;2601 2602	might_sleep();2603 2604	if (!blocked) {2605		/* Turn radio ON */2606		if (phy->radio_on)2607			return;2608 2609		b43_phy_write(dev, 0x0015, 0x8000);2610		b43_phy_write(dev, 0x0015, 0xCC00);2611		b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));2612		if (gphy->radio_off_context.valid) {2613			/* Restore the RFover values. */2614			b43_phy_write(dev, B43_PHY_RFOVER,2615				      gphy->radio_off_context.rfover);2616			b43_phy_write(dev, B43_PHY_RFOVERVAL,2617				      gphy->radio_off_context.rfoverval);2618			gphy->radio_off_context.valid = false;2619		}2620		channel = phy->channel;2621		b43_gphy_channel_switch(dev, 6, 1);2622		b43_gphy_channel_switch(dev, channel, 0);2623	} else {2624		/* Turn radio OFF */2625		u16 rfover, rfoverval;2626 2627		rfover = b43_phy_read(dev, B43_PHY_RFOVER);2628		rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);2629		gphy->radio_off_context.rfover = rfover;2630		gphy->radio_off_context.rfoverval = rfoverval;2631		gphy->radio_off_context.valid = true;2632		b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);2633		b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);2634	}2635}2636 2637static int b43_gphy_op_switch_channel(struct b43_wldev *dev,2638				      unsigned int new_channel)2639{2640	if ((new_channel < 1) || (new_channel > 14))2641		return -EINVAL;2642	b43_gphy_channel_switch(dev, new_channel, 0);2643 2644	return 0;2645}2646 2647static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev)2648{2649	return 1; /* Default to channel 1 */2650}2651 2652static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)2653{2654	struct b43_phy *phy = &dev->phy;2655	u16 tmp;2656	int autodiv = 0;2657 2658	if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)2659		autodiv = 1;2660 2661	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);2662 2663	b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,2664			(autodiv ? B43_ANTENNA_AUTO1 : antenna) <<2665			B43_PHY_BBANDCFG_RXANT_SHIFT);2666 2667	if (autodiv) {2668		tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);2669		if (antenna == B43_ANTENNA_AUTO1)2670			tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;2671		else2672			tmp |= B43_PHY_ANTDWELL_AUTODIV1;2673		b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);2674	}2675 2676	tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);2677	if (autodiv)2678		tmp |= B43_PHY_ANTWRSETT_ARXDIV;2679	else2680		tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;2681	b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);2682 2683	if (autodiv)2684		b43_phy_set(dev, B43_PHY_ANTWRSETT, B43_PHY_ANTWRSETT_ARXDIV);2685	else {2686		b43_phy_mask(dev, B43_PHY_ANTWRSETT,2687			     B43_PHY_ANTWRSETT_ARXDIV);2688	}2689 2690	if (phy->rev >= 2) {2691		b43_phy_set(dev, B43_PHY_OFDM61, B43_PHY_OFDM61_10);2692		b43_phy_maskset(dev, B43_PHY_DIVSRCHGAINBACK, 0xFF00, 0x15);2693 2694		if (phy->rev == 2)2695			b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);2696		else2697			b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);2698	}2699	if (phy->rev >= 6)2700		b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);2701 2702	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);2703}2704 2705static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,2706					 enum b43_interference_mitigation mode)2707{2708	struct b43_phy *phy = &dev->phy;2709	struct b43_phy_g *gphy = phy->g;2710	int currentmode;2711 2712	B43_WARN_ON(phy->type != B43_PHYTYPE_G);2713	if ((phy->rev == 0) || (!phy->gmode))2714		return -ENODEV;2715 2716	gphy->aci_wlan_automatic = false;2717	switch (mode) {2718	case B43_INTERFMODE_AUTOWLAN:2719		gphy->aci_wlan_automatic = true;2720		if (gphy->aci_enable)2721			mode = B43_INTERFMODE_MANUALWLAN;2722		else2723			mode = B43_INTERFMODE_NONE;2724		break;2725	case B43_INTERFMODE_NONE:2726	case B43_INTERFMODE_NONWLAN:2727	case B43_INTERFMODE_MANUALWLAN:2728		break;2729	default:2730		return -EINVAL;2731	}2732 2733	currentmode = gphy->interfmode;2734	if (currentmode == mode)2735		return 0;2736	if (currentmode != B43_INTERFMODE_NONE)2737		b43_radio_interference_mitigation_disable(dev, currentmode);2738 2739	if (mode == B43_INTERFMODE_NONE) {2740		gphy->aci_enable = false;2741		gphy->aci_hw_rssi = false;2742	} else2743		b43_radio_interference_mitigation_enable(dev, mode);2744	gphy->interfmode = mode;2745 2746	return 0;2747}2748 2749/* https://bcm-specs.sipsolutions.net/EstimatePowerOut2750 * This function converts a TSSI value to dBm in Q5.22751 */2752static s8 b43_gphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)2753{2754	struct b43_phy_g *gphy = dev->phy.g;2755	s8 dbm;2756	s32 tmp;2757 2758	tmp = (gphy->tgt_idle_tssi - gphy->cur_idle_tssi + tssi);2759	tmp = clamp_val(tmp, 0x00, 0x3F);2760	dbm = gphy->tssi2dbm[tmp];2761 2762	return dbm;2763}2764 2765static void b43_put_attenuation_into_ranges(struct b43_wldev *dev,2766					    int *_bbatt, int *_rfatt)2767{2768	int rfatt = *_rfatt;2769	int bbatt = *_bbatt;2770	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;2771 2772	/* Get baseband and radio attenuation values into their permitted ranges.2773	 * Radio attenuation affects power level 4 times as much as baseband. */2774 2775	/* Range constants */2776	const int rf_min = lo->rfatt_list.min_val;2777	const int rf_max = lo->rfatt_list.max_val;2778	const int bb_min = lo->bbatt_list.min_val;2779	const int bb_max = lo->bbatt_list.max_val;2780 2781	while (1) {2782		if (rfatt > rf_max && bbatt > bb_max - 4)2783			break;	/* Can not get it into ranges */2784		if (rfatt < rf_min && bbatt < bb_min + 4)2785			break;	/* Can not get it into ranges */2786		if (bbatt > bb_max && rfatt > rf_max - 1)2787			break;	/* Can not get it into ranges */2788		if (bbatt < bb_min && rfatt < rf_min + 1)2789			break;	/* Can not get it into ranges */2790 2791		if (bbatt > bb_max) {2792			bbatt -= 4;2793			rfatt += 1;2794			continue;2795		}2796		if (bbatt < bb_min) {2797			bbatt += 4;2798			rfatt -= 1;2799			continue;2800		}2801		if (rfatt > rf_max) {2802			rfatt -= 1;2803			bbatt += 4;2804			continue;2805		}2806		if (rfatt < rf_min) {2807			rfatt += 1;2808			bbatt -= 4;2809			continue;2810		}2811		break;2812	}2813 2814	*_rfatt = clamp_val(rfatt, rf_min, rf_max);2815	*_bbatt = clamp_val(bbatt, bb_min, bb_max);2816}2817 2818static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)2819{2820	struct b43_phy *phy = &dev->phy;2821	struct b43_phy_g *gphy = phy->g;2822	int rfatt, bbatt;2823	u8 tx_control;2824 2825	b43_mac_suspend(dev);2826 2827	/* Calculate the new attenuation values. */2828	bbatt = gphy->bbatt.att;2829	bbatt += gphy->bbatt_delta;2830	rfatt = gphy->rfatt.att;2831	rfatt += gphy->rfatt_delta;2832 2833	b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);2834	tx_control = gphy->tx_control;2835	if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {2836		if (rfatt <= 1) {2837			if (tx_control == 0) {2838				tx_control =2839				    B43_TXCTL_PA2DB |2840				    B43_TXCTL_TXMIX;2841				rfatt += 2;2842				bbatt += 2;2843			} else if (dev->dev->bus_sprom->2844				   boardflags_lo &2845				   B43_BFL_PACTRL) {2846				bbatt += 4 * (rfatt - 2);2847				rfatt = 2;2848			}2849		} else if (rfatt > 4 && tx_control) {2850			tx_control = 0;2851			if (bbatt < 3) {2852				rfatt -= 3;2853				bbatt += 2;2854			} else {2855				rfatt -= 2;2856				bbatt -= 2;2857			}2858		}2859	}2860	/* Save the control values */2861	gphy->tx_control = tx_control;2862	b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);2863	gphy->rfatt.att = rfatt;2864	gphy->bbatt.att = bbatt;2865 2866	if (b43_debug(dev, B43_DBG_XMITPOWER))2867		b43dbg(dev->wl, "Adjusting TX power\n");2868 2869	/* Adjust the hardware */2870	b43_phy_lock(dev);2871	b43_radio_lock(dev);2872	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt,2873			  gphy->tx_control);2874	b43_radio_unlock(dev);2875	b43_phy_unlock(dev);2876 2877	b43_mac_enable(dev);2878}2879 2880static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,2881							bool ignore_tssi)2882{2883	struct b43_phy *phy = &dev->phy;2884	struct b43_phy_g *gphy = phy->g;2885	unsigned int average_tssi;2886	int cck_result, ofdm_result;2887	int estimated_pwr, desired_pwr, pwr_adjust;2888	int rfatt_delta, bbatt_delta;2889	unsigned int max_pwr;2890 2891	/* First get the average TSSI */2892	cck_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_CCK);2893	ofdm_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_OFDM_G);2894	if ((cck_result < 0) && (ofdm_result < 0)) {2895		/* No TSSI information available */2896		if (!ignore_tssi)2897			goto no_adjustment_needed;2898		cck_result = 0;2899		ofdm_result = 0;2900	}2901	if (cck_result < 0)2902		average_tssi = ofdm_result;2903	else if (ofdm_result < 0)2904		average_tssi = cck_result;2905	else2906		average_tssi = (cck_result + ofdm_result) / 2;2907	/* Merge the average with the stored value. */2908	if (likely(gphy->average_tssi != 0xFF))2909		average_tssi = (average_tssi + gphy->average_tssi) / 2;2910	gphy->average_tssi = average_tssi;2911	B43_WARN_ON(average_tssi >= B43_TSSI_MAX);2912 2913	/* Estimate the TX power emission based on the TSSI */2914	estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);2915 2916	B43_WARN_ON(phy->type != B43_PHYTYPE_G);2917	max_pwr = dev->dev->bus_sprom->maxpwr_bg;2918	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)2919		max_pwr -= 3; /* minus 0.75 */2920	if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {2921		b43warn(dev->wl,2922			"Invalid max-TX-power value in SPROM.\n");2923		max_pwr = INT_TO_Q52(20); /* fake it */2924		dev->dev->bus_sprom->maxpwr_bg = max_pwr;2925	}2926 2927	/* Get desired power (in Q5.2) */2928	if (phy->desired_txpower < 0)2929		desired_pwr = INT_TO_Q52(0);2930	else2931		desired_pwr = INT_TO_Q52(phy->desired_txpower);2932	/* And limit it. max_pwr already is Q5.2 */2933	desired_pwr = clamp_val(desired_pwr, 0, max_pwr);2934	if (b43_debug(dev, B43_DBG_XMITPOWER)) {2935		b43dbg(dev->wl,2936		       "[TX power]  current = " Q52_FMT2937		       " dBm,  desired = " Q52_FMT2938		       " dBm,  max = " Q52_FMT "\n",2939		       Q52_ARG(estimated_pwr),2940		       Q52_ARG(desired_pwr),2941		       Q52_ARG(max_pwr));2942	}2943 2944	/* Calculate the adjustment delta. */2945	pwr_adjust = desired_pwr - estimated_pwr;2946	if (pwr_adjust == 0)2947		goto no_adjustment_needed;2948 2949	/* RF attenuation delta. */2950	rfatt_delta = ((pwr_adjust + 7) / 8);2951	/* Lower attenuation => Bigger power output. Negate it. */2952	rfatt_delta = -rfatt_delta;2953 2954	/* Baseband attenuation delta. */2955	bbatt_delta = pwr_adjust / 2;2956	/* Lower attenuation => Bigger power output. Negate it. */2957	bbatt_delta = -bbatt_delta;2958	/* RF att affects power level 4 times as much as2959	 * Baseband attennuation. Subtract it. */2960	bbatt_delta -= 4 * rfatt_delta;2961 2962#if B43_DEBUG2963	if (b43_debug(dev, B43_DBG_XMITPOWER)) {2964		int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust;2965		b43dbg(dev->wl,2966		       "[TX power deltas]  %s" Q52_FMT " dBm   =>   "2967		       "bbatt-delta = %d,  rfatt-delta = %d\n",2968		       (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm),2969		       bbatt_delta, rfatt_delta);2970	}2971#endif /* DEBUG */2972 2973	/* So do we finally need to adjust something in hardware? */2974	if ((rfatt_delta == 0) && (bbatt_delta == 0))2975		goto no_adjustment_needed;2976 2977	/* Save the deltas for later when we adjust the power. */2978	gphy->bbatt_delta = bbatt_delta;2979	gphy->rfatt_delta = rfatt_delta;2980 2981	/* We need to adjust the TX power on the device. */2982	return B43_TXPWR_RES_NEED_ADJUST;2983 2984no_adjustment_needed:2985	return B43_TXPWR_RES_DONE;2986}2987 2988static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)2989{2990	struct b43_phy *phy = &dev->phy;2991	struct b43_phy_g *gphy = phy->g;2992 2993	b43_mac_suspend(dev);2994	//TODO: update_aci_moving_average2995	if (gphy->aci_enable && gphy->aci_wlan_automatic) {2996		if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {2997			if (0 /*TODO: bunch of conditions */ ) {2998				phy->ops->interf_mitigation(dev,2999					B43_INTERFMODE_MANUALWLAN);3000			}3001		} else if (0 /*TODO*/) {3002			   if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))3003				phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);3004		}3005	} else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&3006		   phy->rev == 1) {3007		//TODO: implement rev1 workaround3008	}3009	b43_lo_g_maintenance_work(dev);3010	b43_mac_enable(dev);3011}3012 3013static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)3014{3015	struct b43_phy *phy = &dev->phy;3016 3017	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))3018		return;3019 3020	b43_mac_suspend(dev);3021	b43_calc_nrssi_slope(dev);3022	if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {3023		u8 old_chan = phy->channel;3024 3025		/* VCO Calibration */3026		if (old_chan >= 8)3027			b43_switch_channel(dev, 1);3028		else3029			b43_switch_channel(dev, 13);3030		b43_switch_channel(dev, old_chan);3031	}3032	b43_mac_enable(dev);3033}3034 3035const struct b43_phy_operations b43_phyops_g = {3036	.allocate		= b43_gphy_op_allocate,3037	.free			= b43_gphy_op_free,3038	.prepare_structs	= b43_gphy_op_prepare_structs,3039	.prepare_hardware	= b43_gphy_op_prepare_hardware,3040	.init			= b43_gphy_op_init,3041	.exit			= b43_gphy_op_exit,3042	.phy_read		= b43_gphy_op_read,3043	.phy_write		= b43_gphy_op_write,3044	.radio_read		= b43_gphy_op_radio_read,3045	.radio_write		= b43_gphy_op_radio_write,3046	.supports_hwpctl	= b43_gphy_op_supports_hwpctl,3047	.software_rfkill	= b43_gphy_op_software_rfkill,3048	.switch_analog		= b43_phyop_switch_analog_generic,3049	.switch_channel		= b43_gphy_op_switch_channel,3050	.get_default_chan	= b43_gphy_op_get_default_chan,3051	.set_rx_antenna		= b43_gphy_op_set_rx_antenna,3052	.interf_mitigation	= b43_gphy_op_interf_mitigation,3053	.recalc_txpower		= b43_gphy_op_recalc_txpower,3054	.adjust_txpower		= b43_gphy_op_adjust_txpower,3055	.pwork_15sec		= b43_gphy_op_pwork_15sec,3056	.pwork_60sec		= b43_gphy_op_pwork_60sec,3057};3058