b43: Implement dynamic PHY API
This patch implements a dynamic "ops" based PHY API. This is needed in order to conveniently support future PHY types to avoid the "switch"-hell. This patch does not change any functionality. It just moves lots of code from one place to another and adjusts it for the changed data structures. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
		
							parent
							
								
									35e032d82f
								
							
						
					
					
						commit
						ef1a628d83
					
				| @ -1,7 +1,9 @@ | ||||
| b43-y				+= main.o | ||||
| b43-y				+= tables.o | ||||
| b43-$(CONFIG_B43_NPHY)		+= tables_nphy.o | ||||
| b43-y				+= phy.o | ||||
| b43-y				+= phy_common.o | ||||
| b43-y				+= phy_g.o | ||||
| b43-y				+= phy_a.o | ||||
| b43-$(CONFIG_B43_NPHY)		+= nphy.o | ||||
| b43-y				+= sysfs.o | ||||
| b43-y				+= xmit.o | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| #include "leds.h" | ||||
| #include "rfkill.h" | ||||
| #include "lo.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| 
 | ||||
| 
 | ||||
| /* The unique identifier of the firmware that's officially supported by
 | ||||
| @ -508,122 +508,6 @@ struct b43_iv { | ||||
| } __attribute__((__packed__)); | ||||
| 
 | ||||
| 
 | ||||
| struct b43_phy { | ||||
| 	/* Band support flags. */ | ||||
| 	bool supports_2ghz; | ||||
| 	bool supports_5ghz; | ||||
| 
 | ||||
| 	/* GMODE bit enabled? */ | ||||
| 	bool gmode; | ||||
| 
 | ||||
| 	/* Analog Type */ | ||||
| 	u8 analog; | ||||
| 	/* B43_PHYTYPE_ */ | ||||
| 	u8 type; | ||||
| 	/* PHY revision number. */ | ||||
| 	u8 rev; | ||||
| 
 | ||||
| 	/* Radio versioning */ | ||||
| 	u16 radio_manuf;	/* Radio manufacturer */ | ||||
| 	u16 radio_ver;		/* Radio version */ | ||||
| 	u8 radio_rev;		/* Radio revision */ | ||||
| 
 | ||||
| 	bool dyn_tssi_tbl;	/* tssi2dbm is kmalloc()ed. */ | ||||
| 
 | ||||
| 	/* ACI (adjacent channel interference) flags. */ | ||||
| 	bool aci_enable; | ||||
| 	bool aci_wlan_automatic; | ||||
| 	bool aci_hw_rssi; | ||||
| 
 | ||||
| 	/* Radio switched on/off */ | ||||
| 	bool radio_on; | ||||
| 	struct { | ||||
| 		/* Values saved when turning the radio off.
 | ||||
| 		 * They are needed when turning it on again. */ | ||||
| 		bool valid; | ||||
| 		u16 rfover; | ||||
| 		u16 rfoverval; | ||||
| 	} radio_off_context; | ||||
| 
 | ||||
| 	u16 minlowsig[2]; | ||||
| 	u16 minlowsigpos[2]; | ||||
| 
 | ||||
| 	/* TSSI to dBm table in use */ | ||||
| 	const s8 *tssi2dbm; | ||||
| 	/* Target idle TSSI */ | ||||
| 	int tgt_idle_tssi; | ||||
| 	/* Current idle TSSI */ | ||||
| 	int cur_idle_tssi; | ||||
| 
 | ||||
| 	/* LocalOscillator control values. */ | ||||
| 	struct b43_txpower_lo_control *lo_control; | ||||
| 	/* Values from b43_calc_loopback_gain() */ | ||||
| 	s16 max_lb_gain;	/* Maximum Loopback gain in hdB */ | ||||
| 	s16 trsw_rx_gain;	/* TRSW RX gain in hdB */ | ||||
| 	s16 lna_lod_gain;	/* LNA lod */ | ||||
| 	s16 lna_gain;		/* LNA */ | ||||
| 	s16 pga_gain;		/* PGA */ | ||||
| 
 | ||||
| 	/* Desired TX power level (in dBm).
 | ||||
| 	 * This is set by the user and adjusted in b43_phy_xmitpower(). */ | ||||
| 	u8 power_level; | ||||
| 	/* A-PHY TX Power control value. */ | ||||
| 	u16 txpwr_offset; | ||||
| 
 | ||||
| 	/* Current TX power level attenuation control values */ | ||||
| 	struct b43_bbatt bbatt; | ||||
| 	struct b43_rfatt rfatt; | ||||
| 	u8 tx_control;		/* B43_TXCTL_XXX */ | ||||
| 
 | ||||
| 	/* Hardware Power Control enabled? */ | ||||
| 	bool hardware_power_control; | ||||
| 
 | ||||
| 	/* Current Interference Mitigation mode */ | ||||
| 	int interfmode; | ||||
| 	/* Stack of saved values from the Interference Mitigation code.
 | ||||
| 	 * Each value in the stack is layed out as follows: | ||||
| 	 * bit 0-11:  offset | ||||
| 	 * bit 12-15: register ID | ||||
| 	 * bit 16-32: value | ||||
| 	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT | ||||
| 	 */ | ||||
| #define B43_INTERFSTACK_SIZE	26 | ||||
| 	u32 interfstack[B43_INTERFSTACK_SIZE];	//FIXME: use a data structure
 | ||||
| 
 | ||||
| 	/* Saved values from the NRSSI Slope calculation */ | ||||
| 	s16 nrssi[2]; | ||||
| 	s32 nrssislope; | ||||
| 	/* In memory nrssi lookup table. */ | ||||
| 	s8 nrssi_lt[64]; | ||||
| 
 | ||||
| 	/* current channel */ | ||||
| 	u8 channel; | ||||
| 
 | ||||
| 	u16 lofcal; | ||||
| 
 | ||||
| 	u16 initval;		//FIXME rename?
 | ||||
| 
 | ||||
| 	/* PHY TX errors counter. */ | ||||
| 	atomic_t txerr_cnt; | ||||
| 
 | ||||
| 	/* The device does address auto increment for the OFDM tables.
 | ||||
| 	 * We cache the previously used address here and omit the address | ||||
| 	 * write on the next table access, if possible. */ | ||||
| 	u16 ofdmtab_addr; /* The address currently set in hardware. */ | ||||
| 	enum { /* The last data flow direction. */ | ||||
| 		B43_OFDMTAB_DIRECTION_UNKNOWN = 0, | ||||
| 		B43_OFDMTAB_DIRECTION_READ, | ||||
| 		B43_OFDMTAB_DIRECTION_WRITE, | ||||
| 	} ofdmtab_addr_direction; | ||||
| 
 | ||||
| #if B43_DEBUG | ||||
| 	/* Manual TX-power control enabled? */ | ||||
| 	bool manual_txpower_control; | ||||
| 	/* PHY registers locked by b43_phy_lock()? */ | ||||
| 	bool phy_locked; | ||||
| #endif /* B43_DEBUG */ | ||||
| }; | ||||
| 
 | ||||
| /* Data structures for DMA transmission, per 80211 core. */ | ||||
| struct b43_dma { | ||||
| 	struct b43_dmaring *tx_ring_AC_BK; /* Background */ | ||||
| @ -908,6 +792,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type) | ||||
| 	return (wl->operating && wl->if_type == type); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_current_band - Returns the currently used band. | ||||
|  * Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ. | ||||
|  */ | ||||
| static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) | ||||
| { | ||||
| 	return wl->hw->conf.channel->band; | ||||
| } | ||||
| 
 | ||||
| static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) | ||||
| { | ||||
| 	return ssb_read16(dev->dev, offset); | ||||
|  | ||||
| @ -443,76 +443,6 @@ out_unlock: | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| static ssize_t txpower_g_read_file(struct b43_wldev *dev, | ||||
| 				   char *buf, size_t bufsize) | ||||
| { | ||||
| 	ssize_t count = 0; | ||||
| 
 | ||||
| 	if (dev->phy.type != B43_PHYTYPE_G) { | ||||
| 		fappend("Device is not a G-PHY\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	fappend("Control:               %s\n", dev->phy.manual_txpower_control ? | ||||
| 		"MANUAL" : "AUTOMATIC"); | ||||
| 	fappend("Baseband attenuation:  %u\n", dev->phy.bbatt.att); | ||||
| 	fappend("Radio attenuation:     %u\n", dev->phy.rfatt.att); | ||||
| 	fappend("TX Mixer Gain:         %s\n", | ||||
| 		(dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF"); | ||||
| 	fappend("PA Gain 2dB:           %s\n", | ||||
| 		(dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF"); | ||||
| 	fappend("PA Gain 3dB:           %s\n", | ||||
| 		(dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF"); | ||||
| 	fappend("\n\n"); | ||||
| 	fappend("You can write to this file:\n"); | ||||
| 	fappend("Writing \"auto\" enables automatic txpower control.\n"); | ||||
| 	fappend | ||||
| 	    ("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" " | ||||
| 	     "enables manual txpower control.\n"); | ||||
| 	fappend("Example: 5 4 0 0 1\n"); | ||||
| 	fappend("Enables manual control with Baseband attenuation 5, " | ||||
| 		"Radio attenuation 4, No TX Mixer Gain, " | ||||
| 		"No PA Gain 2dB, With PA Gain 3dB.\n"); | ||||
| out: | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| static int txpower_g_write_file(struct b43_wldev *dev, | ||||
| 				const char *buf, size_t count) | ||||
| { | ||||
| 	if (dev->phy.type != B43_PHYTYPE_G) | ||||
| 		return -ENODEV; | ||||
| 	if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) { | ||||
| 		/* Automatic control */ | ||||
| 		dev->phy.manual_txpower_control = 0; | ||||
| 		b43_phy_xmitpower(dev); | ||||
| 	} else { | ||||
| 		int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0; | ||||
| 		/* Manual control */ | ||||
| 		if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt, | ||||
| 			   &txmix, &pa2db, &pa3db) != 5) | ||||
| 			return -EINVAL; | ||||
| 		b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); | ||||
| 		dev->phy.manual_txpower_control = 1; | ||||
| 		dev->phy.bbatt.att = bbatt; | ||||
| 		dev->phy.rfatt.att = rfatt; | ||||
| 		dev->phy.tx_control = 0; | ||||
| 		if (txmix) | ||||
| 			dev->phy.tx_control |= B43_TXCTL_TXMIX; | ||||
| 		if (pa2db) | ||||
| 			dev->phy.tx_control |= B43_TXCTL_PA2DB; | ||||
| 		if (pa3db) | ||||
| 			dev->phy.tx_control |= B43_TXCTL_PA3DB; | ||||
| 		b43_phy_lock(dev); | ||||
| 		b43_radio_lock(dev); | ||||
| 		b43_set_txpower_g(dev, &dev->phy.bbatt, | ||||
| 				  &dev->phy.rfatt, dev->phy.tx_control); | ||||
| 		b43_radio_unlock(dev); | ||||
| 		b43_phy_unlock(dev); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* wl->irq_lock is locked */ | ||||
| static int restart_write_file(struct b43_wldev *dev, | ||||
| 			      const char *buf, size_t count) | ||||
| @ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, | ||||
| 		err = -ENODEV; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	lo = phy->lo_control; | ||||
| 	lo = phy->g->lo_control; | ||||
| 	fappend("-- Local Oscillator calibration data --\n\n"); | ||||
| 	fappend("HW-power-control enabled: %d\n", | ||||
| 		dev->phy.hardware_power_control); | ||||
| @ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, | ||||
| 	list_for_each_entry(cal, &lo->calib_list, list) { | ||||
| 		bool active; | ||||
| 
 | ||||
| 		active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | ||||
| 			  b43_compare_rfatt(&cal->rfatt, &phy->rfatt)); | ||||
| 		active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) && | ||||
| 			  b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt)); | ||||
| 		fappend("BB(%d), RF(%d,%d)  ->  I=%d, Q=%d  " | ||||
| 			"(expires in %lu sec)%s\n", | ||||
| 			cal->bbatt.att, | ||||
| @ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); | ||||
| B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); | ||||
| B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); | ||||
| B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); | ||||
| B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); | ||||
| B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); | ||||
| B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); | ||||
| 
 | ||||
| @ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) | ||||
| 	ADD_FILE(mmio32write, 0200); | ||||
| 	ADD_FILE(tsf, 0600); | ||||
| 	ADD_FILE(txstat, 0400); | ||||
| 	ADD_FILE(txpower_g, 0600); | ||||
| 	ADD_FILE(restart, 0200); | ||||
| 	ADD_FILE(loctls, 0400); | ||||
| 
 | ||||
| @ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) | ||||
| 	debugfs_remove(e->file_mmio32write.dentry); | ||||
| 	debugfs_remove(e->file_tsf.dentry); | ||||
| 	debugfs_remove(e->file_txstat.dentry); | ||||
| 	debugfs_remove(e->file_txpower_g.dentry); | ||||
| 	debugfs_remove(e->file_restart.dentry); | ||||
| 	debugfs_remove(e->file_loctls.dentry); | ||||
| 
 | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| 
 | ||||
| #include "b43.h" | ||||
| #include "lo.h" | ||||
| #include "phy.h" | ||||
| #include "phy_g.h" | ||||
| #include "main.h" | ||||
| 
 | ||||
| #include <linux/delay.h> | ||||
| @ -174,7 +174,8 @@ static u16 lo_txctl_register_table(struct b43_wldev *dev, | ||||
| static void lo_measure_txctl_values(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_txpower_lo_control *lo = phy->lo_control; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_txpower_lo_control *lo = gphy->lo_control; | ||||
| 	u16 reg, mask; | ||||
| 	u16 trsw_rx, pga; | ||||
| 	u16 radio_pctl_reg; | ||||
| @ -195,7 +196,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | ||||
| 		int lb_gain;	/* Loopback gain (in dB) */ | ||||
| 
 | ||||
| 		trsw_rx = 0; | ||||
| 		lb_gain = phy->max_lb_gain / 2; | ||||
| 		lb_gain = gphy->max_lb_gain / 2; | ||||
| 		if (lb_gain > 10) { | ||||
| 			radio_pctl_reg = 0; | ||||
| 			pga = abs(10 - lb_gain) / 6; | ||||
| @ -226,7 +227,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | ||||
| 	} | ||||
| 	b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||||
| 				      & 0xFFF0) | radio_pctl_reg); | ||||
| 	b43_phy_set_baseband_attenuation(dev, 2); | ||||
| 	b43_gphy_set_baseband_attenuation(dev, 2); | ||||
| 
 | ||||
| 	reg = lo_txctl_register_table(dev, &mask, NULL); | ||||
| 	mask = ~mask; | ||||
| @ -277,7 +278,8 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | ||||
| static void lo_read_power_vector(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_txpower_lo_control *lo = phy->lo_control; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_txpower_lo_control *lo = gphy->lo_control; | ||||
| 	int i; | ||||
| 	u64 tmp; | ||||
| 	u64 power_vector = 0; | ||||
| @ -298,6 +300,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | ||||
| 				   s16 max_rx_gain, int use_trsw_rx) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	u16 tmp; | ||||
| 
 | ||||
| 	if (max_rx_gain < 0) | ||||
| @ -308,7 +311,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | ||||
| 		int trsw_rx_gain; | ||||
| 
 | ||||
| 		if (use_trsw_rx) { | ||||
| 			trsw_rx_gain = phy->trsw_rx_gain / 2; | ||||
| 			trsw_rx_gain = gphy->trsw_rx_gain / 2; | ||||
| 			if (max_rx_gain >= trsw_rx_gain) { | ||||
| 				trsw_rx_gain = max_rx_gain - trsw_rx_gain; | ||||
| 				trsw_rx = 0x20; | ||||
| @ -316,38 +319,38 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | ||||
| 		} else | ||||
| 			trsw_rx_gain = max_rx_gain; | ||||
| 		if (trsw_rx_gain < 9) { | ||||
| 			phy->lna_lod_gain = 0; | ||||
| 			gphy->lna_lod_gain = 0; | ||||
| 		} else { | ||||
| 			phy->lna_lod_gain = 1; | ||||
| 			gphy->lna_lod_gain = 1; | ||||
| 			trsw_rx_gain -= 8; | ||||
| 		} | ||||
| 		trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); | ||||
| 		phy->pga_gain = trsw_rx_gain / 3; | ||||
| 		if (phy->pga_gain >= 5) { | ||||
| 			phy->pga_gain -= 5; | ||||
| 			phy->lna_gain = 2; | ||||
| 		gphy->pga_gain = trsw_rx_gain / 3; | ||||
| 		if (gphy->pga_gain >= 5) { | ||||
| 			gphy->pga_gain -= 5; | ||||
| 			gphy->lna_gain = 2; | ||||
| 		} else | ||||
| 			phy->lna_gain = 0; | ||||
| 			gphy->lna_gain = 0; | ||||
| 	} else { | ||||
| 		phy->lna_gain = 0; | ||||
| 		phy->trsw_rx_gain = 0x20; | ||||
| 		gphy->lna_gain = 0; | ||||
| 		gphy->trsw_rx_gain = 0x20; | ||||
| 		if (max_rx_gain >= 0x14) { | ||||
| 			phy->lna_lod_gain = 1; | ||||
| 			phy->pga_gain = 2; | ||||
| 			gphy->lna_lod_gain = 1; | ||||
| 			gphy->pga_gain = 2; | ||||
| 		} else if (max_rx_gain >= 0x12) { | ||||
| 			phy->lna_lod_gain = 1; | ||||
| 			phy->pga_gain = 1; | ||||
| 			gphy->lna_lod_gain = 1; | ||||
| 			gphy->pga_gain = 1; | ||||
| 		} else if (max_rx_gain >= 0xF) { | ||||
| 			phy->lna_lod_gain = 1; | ||||
| 			phy->pga_gain = 0; | ||||
| 			gphy->lna_lod_gain = 1; | ||||
| 			gphy->pga_gain = 0; | ||||
| 		} else { | ||||
| 			phy->lna_lod_gain = 0; | ||||
| 			phy->pga_gain = 0; | ||||
| 			gphy->lna_lod_gain = 0; | ||||
| 			gphy->pga_gain = 0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	tmp = b43_radio_read16(dev, 0x7A); | ||||
| 	if (phy->lna_lod_gain == 0) | ||||
| 	if (gphy->lna_lod_gain == 0) | ||||
| 		tmp &= ~0x0008; | ||||
| 	else | ||||
| 		tmp |= 0x0008; | ||||
| @ -392,10 +395,11 @@ static void lo_measure_setup(struct b43_wldev *dev, | ||||
| { | ||||
| 	struct ssb_sprom *sprom = &dev->dev->bus->sprom; | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_txpower_lo_control *lo = phy->lo_control; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_txpower_lo_control *lo = gphy->lo_control; | ||||
| 	u16 tmp; | ||||
| 
 | ||||
| 	if (b43_has_hardware_pctl(phy)) { | ||||
| 	if (b43_has_hardware_pctl(dev)) { | ||||
| 		sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); | ||||
| 		sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); | ||||
| 		sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); | ||||
| @ -496,7 +500,7 @@ static void lo_measure_setup(struct b43_wldev *dev, | ||||
| 		b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); | ||||
| 	if (phy->rev >= 2) | ||||
| 		b43_dummy_transmission(dev); | ||||
| 	b43_radio_selectchannel(dev, 6, 0); | ||||
| 	b43_gphy_channel_switch(dev, 6, 0); | ||||
| 	b43_radio_read16(dev, 0x51);	/* dummy read */ | ||||
| 	if (phy->type == B43_PHYTYPE_G) | ||||
| 		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); | ||||
| @ -520,18 +524,19 @@ static void lo_measure_restore(struct b43_wldev *dev, | ||||
| 			       struct lo_g_saved_values *sav) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	u16 tmp; | ||||
| 
 | ||||
| 	if (phy->rev >= 2) { | ||||
| 		b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); | ||||
| 		tmp = (phy->pga_gain << 8); | ||||
| 		tmp = (gphy->pga_gain << 8); | ||||
| 		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); | ||||
| 		udelay(5); | ||||
| 		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); | ||||
| 		udelay(2); | ||||
| 		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); | ||||
| 	} else { | ||||
| 		tmp = (phy->pga_gain | 0xEFA0); | ||||
| 		tmp = (gphy->pga_gain | 0xEFA0); | ||||
| 		b43_phy_write(dev, B43_PHY_PGACTL, tmp); | ||||
| 	} | ||||
| 	if (phy->type == B43_PHYTYPE_G) { | ||||
| @ -572,7 +577,7 @@ static void lo_measure_restore(struct b43_wldev *dev, | ||||
| 		b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); | ||||
| 		b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); | ||||
| 	} | ||||
| 	if (b43_has_hardware_pctl(phy)) { | ||||
| 	if (b43_has_hardware_pctl(dev)) { | ||||
| 		tmp = (sav->phy_lo_mask & 0xBFFF); | ||||
| 		b43_phy_write(dev, B43_PHY_LO_MASK, tmp); | ||||
| 		b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); | ||||
| @ -580,7 +585,7 @@ static void lo_measure_restore(struct b43_wldev *dev, | ||||
| 		b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); | ||||
| 		b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); | ||||
| 	} | ||||
| 	b43_radio_selectchannel(dev, sav->old_channel, 1); | ||||
| 	b43_gphy_channel_switch(dev, sav->old_channel, 1); | ||||
| } | ||||
| 
 | ||||
| struct b43_lo_g_statemachine { | ||||
| @ -597,6 +602,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | ||||
| 				    struct b43_lo_g_statemachine *d) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_loctl test_loctl; | ||||
| 	struct b43_loctl orig_loctl; | ||||
| 	struct b43_loctl prev_loctl = { | ||||
| @ -646,9 +652,9 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | ||||
| 		     test_loctl.q != prev_loctl.q) && | ||||
| 		    (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { | ||||
| 			b43_lo_write(dev, &test_loctl); | ||||
| 			feedth = lo_measure_feedthrough(dev, phy->lna_gain, | ||||
| 							phy->pga_gain, | ||||
| 							phy->trsw_rx_gain); | ||||
| 			feedth = lo_measure_feedthrough(dev, gphy->lna_gain, | ||||
| 							gphy->pga_gain, | ||||
| 							gphy->trsw_rx_gain); | ||||
| 			if (feedth < d->lowest_feedth) { | ||||
| 				memcpy(probe_loctl, &test_loctl, | ||||
| 				       sizeof(struct b43_loctl)); | ||||
| @ -677,6 +683,7 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | ||||
| 					 int *max_rx_gain) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_lo_g_statemachine d; | ||||
| 	u16 feedth; | ||||
| 	int found_lower; | ||||
| @ -693,17 +700,17 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | ||||
| 		max_repeat = 4; | ||||
| 	do { | ||||
| 		b43_lo_write(dev, &d.min_loctl); | ||||
| 		feedth = lo_measure_feedthrough(dev, phy->lna_gain, | ||||
| 						phy->pga_gain, | ||||
| 						phy->trsw_rx_gain); | ||||
| 		feedth = lo_measure_feedthrough(dev, gphy->lna_gain, | ||||
| 						gphy->pga_gain, | ||||
| 						gphy->trsw_rx_gain); | ||||
| 		if (feedth < 0x258) { | ||||
| 			if (feedth >= 0x12C) | ||||
| 				*max_rx_gain += 6; | ||||
| 			else | ||||
| 				*max_rx_gain += 3; | ||||
| 			feedth = lo_measure_feedthrough(dev, phy->lna_gain, | ||||
| 							phy->pga_gain, | ||||
| 							phy->trsw_rx_gain); | ||||
| 			feedth = lo_measure_feedthrough(dev, gphy->lna_gain, | ||||
| 							gphy->pga_gain, | ||||
| 							gphy->trsw_rx_gain); | ||||
| 		} | ||||
| 		d.lowest_feedth = feedth; | ||||
| 
 | ||||
| @ -752,6 +759,7 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, | ||||
| 					       const struct b43_rfatt *rfatt) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_loctl loctl = { | ||||
| 		.i = 0, | ||||
| 		.q = 0, | ||||
| @ -782,11 +790,11 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, | ||||
| 	if (rfatt->with_padmix) | ||||
| 		max_rx_gain -= pad_mix_gain; | ||||
| 	if (has_loopback_gain(phy)) | ||||
| 		max_rx_gain += phy->max_lb_gain; | ||||
| 		max_rx_gain += gphy->max_lb_gain; | ||||
| 	lo_measure_gain_values(dev, max_rx_gain, | ||||
| 			       has_loopback_gain(phy)); | ||||
| 
 | ||||
| 	b43_phy_set_baseband_attenuation(dev, bbatt->att); | ||||
| 	b43_gphy_set_baseband_attenuation(dev, bbatt->att); | ||||
| 	lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); | ||||
| 
 | ||||
| 	lo_measure_restore(dev, &saved_regs); | ||||
| @ -820,7 +828,7 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, | ||||
| 						const struct b43_bbatt *bbatt, | ||||
| 						const struct b43_rfatt *rfatt) | ||||
| { | ||||
| 	struct b43_txpower_lo_control *lo = dev->phy.lo_control; | ||||
| 	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; | ||||
| 	struct b43_lo_calib *c; | ||||
| 
 | ||||
| 	c = b43_find_lo_calib(lo, bbatt, rfatt); | ||||
| @ -839,7 +847,8 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, | ||||
| void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_txpower_lo_control *lo = phy->lo_control; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_txpower_lo_control *lo = gphy->lo_control; | ||||
| 	int i; | ||||
| 	int rf_offset, bb_offset; | ||||
| 	const struct b43_rfatt *rfatt; | ||||
| @ -917,14 +926,14 @@ static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) | ||||
| 
 | ||||
| void b43_lo_g_adjust(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = dev->phy.g; | ||||
| 	struct b43_lo_calib *cal; | ||||
| 	struct b43_rfatt rf; | ||||
| 
 | ||||
| 	memcpy(&rf, &phy->rfatt, sizeof(rf)); | ||||
| 	memcpy(&rf, &gphy->rfatt, sizeof(rf)); | ||||
| 	b43_lo_fixup_rfatt(&rf); | ||||
| 
 | ||||
| 	cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf); | ||||
| 	cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf); | ||||
| 	if (!cal) | ||||
| 		return; | ||||
| 	b43_lo_write(dev, &cal->ctl); | ||||
| @ -952,7 +961,8 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev, | ||||
| void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_txpower_lo_control *lo = phy->lo_control; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	struct b43_txpower_lo_control *lo = gphy->lo_control; | ||||
| 	unsigned long now; | ||||
| 	unsigned long expire; | ||||
| 	struct b43_lo_calib *cal, *tmp; | ||||
| @ -962,7 +972,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||||
| 	if (!lo) | ||||
| 		return; | ||||
| 	now = jiffies; | ||||
| 	hwpctl = b43_has_hardware_pctl(phy); | ||||
| 	hwpctl = b43_has_hardware_pctl(dev); | ||||
| 
 | ||||
| 	if (hwpctl) { | ||||
| 		/* Read the power vector and update it, if needed. */ | ||||
| @ -983,8 +993,8 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||||
| 		if (!time_before(cal->calib_time, expire)) | ||||
| 			continue; | ||||
| 		/* This item expired. */ | ||||
| 		if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | ||||
| 		    b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) { | ||||
| 		if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) && | ||||
| 		    b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) { | ||||
| 			B43_WARN_ON(current_item_expired); | ||||
| 			current_item_expired = 1; | ||||
| 		} | ||||
| @ -1002,7 +1012,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||||
| 		/* Recalibrate currently used LO setting. */ | ||||
| 		if (b43_debug(dev, B43_DBG_LO)) | ||||
| 			b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); | ||||
| 		cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt); | ||||
| 		cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt); | ||||
| 		if (cal) { | ||||
| 			list_add(&cal->list, &lo->calib_list); | ||||
| 			b43_lo_write(dev, &cal->ctl); | ||||
| @ -1013,7 +1023,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||||
| 
 | ||||
| void b43_lo_g_cleanup(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_txpower_lo_control *lo = dev->phy.lo_control; | ||||
| 	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; | ||||
| 	struct b43_lo_calib *cal, *tmp; | ||||
| 
 | ||||
| 	if (!lo) | ||||
| @ -1027,9 +1037,7 @@ void b43_lo_g_cleanup(struct b43_wldev *dev) | ||||
| /* LO Initialization */ | ||||
| void b43_lo_g_init(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 
 | ||||
| 	if (b43_has_hardware_pctl(phy)) { | ||||
| 	if (b43_has_hardware_pctl(dev)) { | ||||
| 		lo_read_power_vector(dev); | ||||
| 		b43_gphy_dc_lt_init(dev, 1); | ||||
| 	} | ||||
|  | ||||
| @ -1,7 +1,9 @@ | ||||
| #ifndef B43_LO_H_ | ||||
| #define B43_LO_H_ | ||||
| 
 | ||||
| #include "phy.h" | ||||
| /* G-PHY Local Oscillator */ | ||||
| 
 | ||||
| #include "phy_g.h" | ||||
| 
 | ||||
| struct b43_wldev; | ||||
| 
 | ||||
|  | ||||
| @ -44,7 +44,8 @@ | ||||
| #include "b43.h" | ||||
| #include "main.h" | ||||
| #include "debugfs.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| #include "phy_g.h" | ||||
| #include "nphy.h" | ||||
| #include "dma.h" | ||||
| #include "pio.h" | ||||
| @ -1174,6 +1175,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | ||||
| { | ||||
| 	/* Top half of Link Quality calculation. */ | ||||
| 
 | ||||
| 	if (dev->phy.type != B43_PHYTYPE_G) | ||||
| 		return; | ||||
| 	if (dev->noisecalc.calculation_running) | ||||
| 		return; | ||||
| 	dev->noisecalc.calculation_running = 1; | ||||
| @ -1184,7 +1187,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | ||||
| 
 | ||||
| static void handle_irq_noise(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *phy = dev->phy.g; | ||||
| 	u16 tmp; | ||||
| 	u8 noise[4]; | ||||
| 	u8 i, j; | ||||
| @ -1192,6 +1195,9 @@ static void handle_irq_noise(struct b43_wldev *dev) | ||||
| 
 | ||||
| 	/* Bottom half of Link Quality calculation. */ | ||||
| 
 | ||||
| 	if (dev->phy.type != B43_PHYTYPE_G) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Possible race condition: It might be possible that the user
 | ||||
| 	 * changed to a different channel in the meantime since we | ||||
| 	 * started the calculation. We ignore that fact, since it's | ||||
| @ -2688,9 +2694,7 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) | ||||
| /* This is the opposite of b43_chip_init() */ | ||||
| static void b43_chip_exit(struct b43_wldev *dev) | ||||
| { | ||||
| 	b43_radio_turn_off(dev, 1); | ||||
| 	b43_gpio_cleanup(dev); | ||||
| 	b43_lo_g_cleanup(dev); | ||||
| 	/* firmware is released later */ | ||||
| } | ||||
| 
 | ||||
| @ -2700,7 +2704,7 @@ static void b43_chip_exit(struct b43_wldev *dev) | ||||
| static int b43_chip_init(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	int err, tmp; | ||||
| 	int err; | ||||
| 	u32 value32, macctl; | ||||
| 	u16 value16; | ||||
| 
 | ||||
| @ -2725,19 +2729,19 @@ static int b43_chip_init(struct b43_wldev *dev) | ||||
| 	err = b43_upload_initvals(dev); | ||||
| 	if (err) | ||||
| 		goto err_gpio_clean; | ||||
| 	b43_radio_turn_on(dev); | ||||
| 
 | ||||
| 	b43_write16(dev, 0x03E6, 0x0000); | ||||
| 	err = b43_phy_init(dev); | ||||
| 	if (err) | ||||
| 		goto err_radio_off; | ||||
| 		goto err_gpio_clean; | ||||
| 
 | ||||
| 	/* Select initial Interference Mitigation. */ | ||||
| 	tmp = phy->interfmode; | ||||
| 	phy->interfmode = B43_INTERFMODE_NONE; | ||||
| 	b43_radio_set_interference_mitigation(dev, tmp); | ||||
| 	/* Disable Interference Mitigation. */ | ||||
| 	if (phy->ops->interf_mitigation) | ||||
| 		phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); | ||||
| 
 | ||||
| 	b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | ||||
| 	/* Select the antennae */ | ||||
| 	if (phy->ops->set_rx_antenna) | ||||
| 		phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | ||||
| 	b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); | ||||
| 
 | ||||
| 	if (phy->type == B43_PHYTYPE_B) { | ||||
| @ -2790,8 +2794,6 @@ static int b43_chip_init(struct b43_wldev *dev) | ||||
| out: | ||||
| 	return err; | ||||
| 
 | ||||
| err_radio_off: | ||||
| 	b43_radio_turn_off(dev, 1); | ||||
| err_gpio_clean: | ||||
| 	b43_gpio_cleanup(dev); | ||||
| 	return err; | ||||
| @ -2799,25 +2801,10 @@ err_gpio_clean: | ||||
| 
 | ||||
| static void b43_periodic_every60sec(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	const struct b43_phy_operations *ops = dev->phy.ops; | ||||
| 
 | ||||
| 	if (phy->type != B43_PHYTYPE_G) | ||||
| 		return; | ||||
| 	if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { | ||||
| 		b43_mac_suspend(dev); | ||||
| 		b43_calc_nrssi_slope(dev); | ||||
| 		if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { | ||||
| 			u8 old_chan = phy->channel; | ||||
| 
 | ||||
| 			/* VCO Calibration */ | ||||
| 			if (old_chan >= 8) | ||||
| 				b43_radio_selectchannel(dev, 1, 0); | ||||
| 			else | ||||
| 				b43_radio_selectchannel(dev, 13, 0); | ||||
| 			b43_radio_selectchannel(dev, old_chan, 0); | ||||
| 		} | ||||
| 		b43_mac_enable(dev); | ||||
| 	} | ||||
| 	if (ops->pwork_60sec) | ||||
| 		ops->pwork_60sec(dev); | ||||
| } | ||||
| 
 | ||||
| static void b43_periodic_every30sec(struct b43_wldev *dev) | ||||
| @ -2845,32 +2832,10 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (phy->type == B43_PHYTYPE_G) { | ||||
| 		//TODO: update_aci_moving_average
 | ||||
| 		if (phy->aci_enable && phy->aci_wlan_automatic) { | ||||
| 			b43_mac_suspend(dev); | ||||
| 			if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) { | ||||
| 				if (0 /*TODO: bunch of conditions */ ) { | ||||
| 					b43_radio_set_interference_mitigation | ||||
| 					    (dev, B43_INTERFMODE_MANUALWLAN); | ||||
| 				} | ||||
| 			} else if (1 /*TODO*/) { | ||||
| 				/*
 | ||||
| 				   if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) { | ||||
| 				   b43_radio_set_interference_mitigation(dev, | ||||
| 				   B43_INTERFMODE_NONE); | ||||
| 				   } | ||||
| 				 */ | ||||
| 			} | ||||
| 			b43_mac_enable(dev); | ||||
| 		} else if (phy->interfmode == B43_INTERFMODE_NONWLAN && | ||||
| 			   phy->rev == 1) { | ||||
| 			//TODO: implement rev1 workaround
 | ||||
| 		} | ||||
| 	} | ||||
| 	b43_phy_xmitpower(dev);	//FIXME: unless scanning?
 | ||||
| 	b43_lo_g_maintanance_work(dev); | ||||
| 	//TODO for APHY (temperature?)
 | ||||
| 	if (phy->ops->pwork_15sec) | ||||
| 		phy->ops->pwork_15sec(dev); | ||||
| 
 | ||||
| 	phy->ops->xmitpower(dev); | ||||
| 
 | ||||
| 	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | ||||
| 	wmb(); | ||||
| @ -3401,7 +3366,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | ||||
| 	/* Switch to the requested channel.
 | ||||
| 	 * The firmware takes care of races with the TX handler. */ | ||||
| 	if (conf->channel->hw_value != phy->channel) | ||||
| 		b43_radio_selectchannel(dev, conf->channel->hw_value, 0); | ||||
| 		b43_switch_channel(dev, conf->channel->hw_value); | ||||
| 
 | ||||
| 	/* Enable/Disable ShortSlot timing. */ | ||||
| 	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != | ||||
| @ -3419,7 +3384,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | ||||
| 	if (conf->power_level != 0) { | ||||
| 		if (conf->power_level != phy->power_level) { | ||||
| 			phy->power_level = conf->power_level; | ||||
| 			b43_phy_xmitpower(dev); | ||||
| 			phy->ops->xmitpower(dev); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -3427,7 +3392,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | ||||
| 	antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); | ||||
| 	b43_mgmtframe_txantenna(dev, antenna); | ||||
| 	antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); | ||||
| 	b43_set_rx_antenna(dev, antenna); | ||||
| 	if (phy->ops->set_rx_antenna) | ||||
| 		phy->ops->set_rx_antenna(dev, antenna); | ||||
| 
 | ||||
| 	/* Update templates for AP/mesh mode. */ | ||||
| 	if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || | ||||
| @ -3436,7 +3402,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | ||||
| 
 | ||||
| 	if (!!conf->radio_enabled != phy->radio_on) { | ||||
| 		if (conf->radio_enabled) { | ||||
| 			b43_radio_turn_on(dev); | ||||
| 			b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); | ||||
| 			b43info(dev->wl, "Radio turned on by software\n"); | ||||
| 			if (!dev->radio_hw_enable) { | ||||
| 				b43info(dev->wl, "The hardware RF-kill button " | ||||
| @ -3444,7 +3410,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | ||||
| 					"Press the button to turn it on.\n"); | ||||
| 			} | ||||
| 		} else { | ||||
| 			b43_radio_turn_off(dev, 0); | ||||
| 			b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); | ||||
| 			b43info(dev->wl, "Radio turned off by software\n"); | ||||
| 		} | ||||
| 	} | ||||
| @ -3818,48 +3784,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | ||||
| static void setup_struct_phy_for_init(struct b43_wldev *dev, | ||||
| 				      struct b43_phy *phy) | ||||
| { | ||||
| 	struct b43_txpower_lo_control *lo; | ||||
| 	int i; | ||||
| 
 | ||||
| 	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); | ||||
| 	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); | ||||
| 
 | ||||
| 	phy->aci_enable = 0; | ||||
| 	phy->aci_wlan_automatic = 0; | ||||
| 	phy->aci_hw_rssi = 0; | ||||
| 
 | ||||
| 	phy->radio_off_context.valid = 0; | ||||
| 
 | ||||
| 	lo = phy->lo_control; | ||||
| 	if (lo) { | ||||
| 		memset(lo, 0, sizeof(*(phy->lo_control))); | ||||
| 		lo->tx_bias = 0xFF; | ||||
| 		INIT_LIST_HEAD(&lo->calib_list); | ||||
| 	} | ||||
| 	phy->max_lb_gain = 0; | ||||
| 	phy->trsw_rx_gain = 0; | ||||
| 	phy->txpwr_offset = 0; | ||||
| 
 | ||||
| 	/* NRSSI */ | ||||
| 	phy->nrssislope = 0; | ||||
| 	for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++) | ||||
| 		phy->nrssi[i] = -1000; | ||||
| 	for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++) | ||||
| 		phy->nrssi_lt[i] = i; | ||||
| 
 | ||||
| 	phy->lofcal = 0xFFFF; | ||||
| 	phy->initval = 0xFFFF; | ||||
| 
 | ||||
| 	phy->interfmode = B43_INTERFMODE_NONE; | ||||
| 	phy->channel = 0xFF; | ||||
| 
 | ||||
| 	phy->hardware_power_control = !!modparam_hwpctl; | ||||
| 
 | ||||
| 	/* PHY TX errors counter. */ | ||||
| 	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | ||||
| 
 | ||||
| 	/* OFDM-table address caching. */ | ||||
| 	phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| static void setup_struct_wldev_for_init(struct b43_wldev *dev) | ||||
| @ -3995,7 +3922,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev) | ||||
| /* Locking: wl->mutex */ | ||||
| static void b43_wireless_core_exit(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	u32 macctl; | ||||
| 
 | ||||
| 	B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); | ||||
| @ -4016,16 +3942,12 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | ||||
| 	b43_dma_free(dev); | ||||
| 	b43_pio_free(dev); | ||||
| 	b43_chip_exit(dev); | ||||
| 	b43_radio_turn_off(dev, 1); | ||||
| 	b43_switch_analog(dev, 0); | ||||
| 	if (phy->dyn_tssi_tbl) | ||||
| 		kfree(phy->tssi2dbm); | ||||
| 	kfree(phy->lo_control); | ||||
| 	phy->lo_control = NULL; | ||||
| 	if (dev->wl->current_beacon) { | ||||
| 		dev_kfree_skb_any(dev->wl->current_beacon); | ||||
| 		dev->wl->current_beacon = NULL; | ||||
| 	} | ||||
| 	b43_phy_exit(dev); | ||||
| 
 | ||||
| 	ssb_device_disable(dev->dev, 0); | ||||
| 	ssb_bus_may_powerdown(dev->dev->bus); | ||||
| @ -4052,29 +3974,24 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | ||||
| 		b43_wireless_core_reset(dev, tmp); | ||||
| 	} | ||||
| 
 | ||||
| 	if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) { | ||||
| 		phy->lo_control = | ||||
| 		    kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL); | ||||
| 		if (!phy->lo_control) { | ||||
| 			err = -ENOMEM; | ||||
| 			goto err_busdown; | ||||
| 		} | ||||
| 	} | ||||
| 	setup_struct_wldev_for_init(dev); | ||||
| 
 | ||||
| 	err = b43_phy_init_tssi2dbm_table(dev); | ||||
| 	err = b43_phy_operations_setup(dev); | ||||
| 	if (err) | ||||
| 		goto err_kfree_lo_control; | ||||
| 		goto err_busdown; | ||||
| 
 | ||||
| 	/* Enable IRQ routing to this device. */ | ||||
| 	ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); | ||||
| 
 | ||||
| 	b43_imcfglo_timeouts_workaround(dev); | ||||
| 	b43_bluetooth_coext_disable(dev); | ||||
| 	b43_phy_early_init(dev); | ||||
| 	if (phy->ops->prepare) { | ||||
| 		err = phy->ops->prepare(dev); | ||||
| 		if (err) | ||||
| 			goto err_phy_exit; | ||||
| 	} | ||||
| 	err = b43_chip_init(dev); | ||||
| 	if (err) | ||||
| 		goto err_kfree_tssitbl; | ||||
| 		goto err_phy_exit; | ||||
| 	b43_shm_write16(dev, B43_SHM_SHARED, | ||||
| 			B43_SHM_SH_WLCOREREV, dev->dev->id.revision); | ||||
| 	hf = b43_hf_read(dev); | ||||
| @ -4140,15 +4057,11 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | ||||
| out: | ||||
| 	return err; | ||||
| 
 | ||||
|       err_chip_exit: | ||||
| err_chip_exit: | ||||
| 	b43_chip_exit(dev); | ||||
|       err_kfree_tssitbl: | ||||
| 	if (phy->dyn_tssi_tbl) | ||||
| 		kfree(phy->tssi2dbm); | ||||
|       err_kfree_lo_control: | ||||
| 	kfree(phy->lo_control); | ||||
| 	phy->lo_control = NULL; | ||||
|       err_busdown: | ||||
| err_phy_exit: | ||||
| 	b43_phy_exit(dev); | ||||
| err_busdown: | ||||
| 	ssb_bus_may_powerdown(bus); | ||||
| 	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); | ||||
| 	return err; | ||||
| @ -4511,7 +4424,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | ||||
| 		wl->current_dev = dev; | ||||
| 	INIT_WORK(&dev->restart_work, b43_chip_reset); | ||||
| 
 | ||||
| 	b43_radio_turn_off(dev, 1); | ||||
| 	b43_switch_analog(dev, 0); | ||||
| 	ssb_device_disable(dev->dev, 0); | ||||
| 	ssb_bus_may_powerdown(bus); | ||||
|  | ||||
| @ -81,9 +81,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | ||||
| 	//TODO
 | ||||
| } | ||||
| 
 | ||||
| /* Tune the hardware to a new channel. Don't call this directly.
 | ||||
|  * Use b43_radio_selectchannel() */ | ||||
| int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) | ||||
| /* Tune the hardware to a new channel. */ | ||||
| static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||||
| { | ||||
| 	const struct b43_nphy_channeltab_entry *tabent; | ||||
| 
 | ||||
| @ -162,7 +161,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) | ||||
| 	msleep(1); | ||||
| 	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | ||||
| 	msleep(1); | ||||
| 	b43_radio_selectchannel(dev, dev->phy.channel, 0); | ||||
| 	nphy_channel_switch(dev, dev->phy.channel); | ||||
| 	b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); | ||||
| 	b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); | ||||
| 	b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | ||||
| @ -484,3 +483,139 @@ int b43_phy_initn(struct b43_wldev *dev) | ||||
| 	b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int b43_nphy_op_allocate(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_n *nphy; | ||||
| 
 | ||||
| 	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); | ||||
| 	if (!nphy) | ||||
| 		return -ENOMEM; | ||||
| 	dev->phy.n = nphy; | ||||
| 
 | ||||
| 	//TODO init struct b43_phy_n
 | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int b43_nphy_op_init(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_n *nphy = dev->phy.n; | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = b43_phy_initn(dev); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 	nphy->initialised = 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void b43_nphy_op_exit(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_n *nphy = dev->phy.n; | ||||
| 
 | ||||
| 	if (nphy->initialised) { | ||||
| 		//TODO
 | ||||
| 		nphy->initialised = 0; | ||||
| 	} | ||||
| 	//TODO
 | ||||
| 	kfree(nphy); | ||||
| 	dev->phy.n = NULL; | ||||
| } | ||||
| 
 | ||||
| static inline void check_phyreg(struct b43_wldev *dev, u16 offset) | ||||
| { | ||||
| #if B43_DEBUG | ||||
| 	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { | ||||
| 		/* OFDM registers are onnly available on A/G-PHYs */ | ||||
| 		b43err(dev->wl, "Invalid OFDM PHY access at " | ||||
| 		       "0x%04X on N-PHY\n", offset); | ||||
| 		dump_stack(); | ||||
| 	} | ||||
| 	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { | ||||
| 		/* Ext-G registers are only available on G-PHYs */ | ||||
| 		b43err(dev->wl, "Invalid EXT-G PHY access at " | ||||
| 		       "0x%04X on N-PHY\n", offset); | ||||
| 		dump_stack(); | ||||
| 	} | ||||
| #endif /* B43_DEBUG */ | ||||
| } | ||||
| 
 | ||||
| static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	check_phyreg(dev, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||||
| 	return b43_read16(dev, B43_MMIO_PHY_DATA); | ||||
| } | ||||
| 
 | ||||
| static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	check_phyreg(dev, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_DATA, value); | ||||
| } | ||||
| 
 | ||||
| static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	/* Register 1 is a 32-bit register. */ | ||||
| 	B43_WARN_ON(reg == 1); | ||||
| 	/* N-PHY needs 0x100 for read access */ | ||||
| 	reg |= 0x100; | ||||
| 
 | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||||
| 	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||||
| } | ||||
| 
 | ||||
| static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	/* Register 1 is a 32-bit register. */ | ||||
| 	B43_WARN_ON(reg == 1); | ||||
| 
 | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | ||||
| } | ||||
| 
 | ||||
| static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | ||||
| 					enum rfkill_state state) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| static int b43_nphy_op_switch_channel(struct b43_wldev *dev, | ||||
| 				      unsigned int new_channel) | ||||
| { | ||||
| 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||||
| 		if ((new_channel < 1) || (new_channel > 14)) | ||||
| 			return -EINVAL; | ||||
| 	} else { | ||||
| 		if (new_channel > 200) | ||||
| 			return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	return nphy_channel_switch(dev, new_channel); | ||||
| } | ||||
| 
 | ||||
| static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) | ||||
| { | ||||
| 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||||
| 		return 1; | ||||
| 	return 36; | ||||
| } | ||||
| 
 | ||||
| static void b43_nphy_op_xmitpower(struct b43_wldev *dev) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| const struct b43_phy_operations b43_phyops_n = { | ||||
| 	.allocate		= b43_nphy_op_allocate, | ||||
| 	.init			= b43_nphy_op_init, | ||||
| 	.exit			= b43_nphy_op_exit, | ||||
| 	.phy_read		= b43_nphy_op_read, | ||||
| 	.phy_write		= b43_nphy_op_write, | ||||
| 	.radio_read		= b43_nphy_op_radio_read, | ||||
| 	.radio_write		= b43_nphy_op_radio_write, | ||||
| 	.software_rfkill	= b43_nphy_op_software_rfkill, | ||||
| 	.switch_channel		= b43_nphy_op_switch_channel, | ||||
| 	.get_default_chan	= b43_nphy_op_get_default_chan, | ||||
| 	.xmitpower		= b43_nphy_op_xmitpower, | ||||
| }; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| #ifndef B43_NPHY_H_ | ||||
| #define B43_NPHY_H_ | ||||
| 
 | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| 
 | ||||
| 
 | ||||
| /* N-PHY registers. */ | ||||
| @ -919,54 +919,14 @@ | ||||
| 
 | ||||
| struct b43_wldev; | ||||
| 
 | ||||
| struct b43_phy_n { | ||||
| 	bool initialised; | ||||
| 
 | ||||
| #ifdef CONFIG_B43_NPHY | ||||
| /* N-PHY support enabled */ | ||||
| 
 | ||||
| int b43_phy_initn(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_nphy_radio_turn_on(struct b43_wldev *dev); | ||||
| void b43_nphy_radio_turn_off(struct b43_wldev *dev); | ||||
| 
 | ||||
| int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel); | ||||
| 
 | ||||
| void b43_nphy_xmitpower(struct b43_wldev *dev); | ||||
| void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna); | ||||
| 	//TODO lots of missing stuff
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #else /* CONFIG_B43_NPHY */ | ||||
| /* N-PHY support disabled */ | ||||
| struct b43_phy_operations; | ||||
| extern const struct b43_phy_operations b43_phyops_n; | ||||
| 
 | ||||
| 
 | ||||
| static inline | ||||
| int b43_phy_initn(struct b43_wldev *dev) | ||||
| { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| 
 | ||||
| static inline | ||||
| void b43_nphy_radio_turn_on(struct b43_wldev *dev) | ||||
| { | ||||
| } | ||||
| static inline | ||||
| void b43_nphy_radio_turn_off(struct b43_wldev *dev) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static inline | ||||
| int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) | ||||
| { | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| static inline | ||||
| void b43_nphy_xmitpower(struct b43_wldev *dev) | ||||
| { | ||||
| } | ||||
| static inline | ||||
| void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_B43_NPHY */ | ||||
| #endif /* B43_NPHY_H_ */ | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,340 +0,0 @@ | ||||
| #ifndef B43_PHY_H_ | ||||
| #define B43_PHY_H_ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| struct b43_wldev; | ||||
| struct b43_phy; | ||||
| 
 | ||||
| /*** PHY Registers ***/ | ||||
| 
 | ||||
| /* Routing */ | ||||
| #define B43_PHYROUTE			0x0C00 /* PHY register routing bits mask */ | ||||
| #define  B43_PHYROUTE_BASE		0x0000 /* Base registers */ | ||||
| #define  B43_PHYROUTE_OFDM_GPHY		0x0400 /* OFDM register routing for G-PHYs */ | ||||
| #define  B43_PHYROUTE_EXT_GPHY		0x0800 /* Extended G-PHY registers */ | ||||
| #define  B43_PHYROUTE_N_BMODE		0x0C00 /* N-PHY BMODE registers */ | ||||
| 
 | ||||
| /* CCK (B-PHY) registers. */ | ||||
| #define B43_PHY_CCK(reg)		((reg) | B43_PHYROUTE_BASE) | ||||
| /* N-PHY registers. */ | ||||
| #define B43_PHY_N(reg)			((reg) | B43_PHYROUTE_BASE) | ||||
| /* N-PHY BMODE registers. */ | ||||
| #define B43_PHY_N_BMODE(reg)		((reg) | B43_PHYROUTE_N_BMODE) | ||||
| /* OFDM (A-PHY) registers. */ | ||||
| #define B43_PHY_OFDM(reg)		((reg) | B43_PHYROUTE_OFDM_GPHY) | ||||
| /* Extended G-PHY registers. */ | ||||
| #define B43_PHY_EXTG(reg)		((reg) | B43_PHYROUTE_EXT_GPHY) | ||||
| 
 | ||||
| /* OFDM (A) PHY Registers */ | ||||
| #define B43_PHY_VERSION_OFDM		B43_PHY_OFDM(0x00)	/* Versioning register for A-PHY */ | ||||
| #define B43_PHY_BBANDCFG		B43_PHY_OFDM(0x01)	/* Baseband config */ | ||||
| #define  B43_PHY_BBANDCFG_RXANT		0x180	/* RX Antenna selection */ | ||||
| #define  B43_PHY_BBANDCFG_RXANT_SHIFT	7 | ||||
| #define B43_PHY_PWRDOWN			B43_PHY_OFDM(0x03)	/* Powerdown */ | ||||
| #define B43_PHY_CRSTHRES1_R1		B43_PHY_OFDM(0x06)	/* CRS Threshold 1 (phy.rev 1 only) */ | ||||
| #define B43_PHY_LNAHPFCTL		B43_PHY_OFDM(0x1C)	/* LNA/HPF control */ | ||||
| #define B43_PHY_LPFGAINCTL		B43_PHY_OFDM(0x20)	/* LPF Gain control */ | ||||
| #define B43_PHY_ADIVRELATED		B43_PHY_OFDM(0x27)	/* FIXME rename */ | ||||
| #define B43_PHY_CRS0			B43_PHY_OFDM(0x29) | ||||
| #define  B43_PHY_CRS0_EN		0x4000 | ||||
| #define B43_PHY_PEAK_COUNT		B43_PHY_OFDM(0x30) | ||||
| #define B43_PHY_ANTDWELL		B43_PHY_OFDM(0x2B)	/* Antenna dwell */ | ||||
| #define  B43_PHY_ANTDWELL_AUTODIV1	0x0100	/* Automatic RX diversity start antenna */ | ||||
| #define B43_PHY_ENCORE			B43_PHY_OFDM(0x49)	/* "Encore" (RangeMax / BroadRange) */ | ||||
| #define  B43_PHY_ENCORE_EN		0x0200	/* Encore enable */ | ||||
| #define B43_PHY_LMS			B43_PHY_OFDM(0x55) | ||||
| #define B43_PHY_OFDM61			B43_PHY_OFDM(0x61)	/* FIXME rename */ | ||||
| #define  B43_PHY_OFDM61_10		0x0010	/* FIXME rename */ | ||||
| #define B43_PHY_IQBAL			B43_PHY_OFDM(0x69)	/* I/Q balance */ | ||||
| #define B43_PHY_BBTXDC_BIAS		B43_PHY_OFDM(0x6B)	/* Baseband TX DC bias */ | ||||
| #define B43_PHY_OTABLECTL		B43_PHY_OFDM(0x72)	/* OFDM table control (see below) */ | ||||
| #define  B43_PHY_OTABLEOFF		0x03FF	/* OFDM table offset (see below) */ | ||||
| #define  B43_PHY_OTABLENR		0xFC00	/* OFDM table number (see below) */ | ||||
| #define  B43_PHY_OTABLENR_SHIFT		10 | ||||
| #define B43_PHY_OTABLEI			B43_PHY_OFDM(0x73)	/* OFDM table data I */ | ||||
| #define B43_PHY_OTABLEQ			B43_PHY_OFDM(0x74)	/* OFDM table data Q */ | ||||
| #define B43_PHY_HPWR_TSSICTL		B43_PHY_OFDM(0x78)	/* Hardware power TSSI control */ | ||||
| #define B43_PHY_ADCCTL			B43_PHY_OFDM(0x7A)	/* ADC control */ | ||||
| #define B43_PHY_IDLE_TSSI		B43_PHY_OFDM(0x7B) | ||||
| #define B43_PHY_A_TEMP_SENSE		B43_PHY_OFDM(0x7C)	/* A PHY temperature sense */ | ||||
| #define B43_PHY_NRSSITHRES		B43_PHY_OFDM(0x8A)	/* NRSSI threshold */ | ||||
| #define B43_PHY_ANTWRSETT		B43_PHY_OFDM(0x8C)	/* Antenna WR settle */ | ||||
| #define  B43_PHY_ANTWRSETT_ARXDIV	0x2000	/* Automatic RX diversity enabled */ | ||||
| #define B43_PHY_CLIPPWRDOWNT		B43_PHY_OFDM(0x93)	/* Clip powerdown threshold */ | ||||
| #define B43_PHY_OFDM9B			B43_PHY_OFDM(0x9B)	/* FIXME rename */ | ||||
| #define B43_PHY_N1P1GAIN		B43_PHY_OFDM(0xA0) | ||||
| #define B43_PHY_P1P2GAIN		B43_PHY_OFDM(0xA1) | ||||
| #define B43_PHY_N1N2GAIN		B43_PHY_OFDM(0xA2) | ||||
| #define B43_PHY_CLIPTHRES		B43_PHY_OFDM(0xA3) | ||||
| #define B43_PHY_CLIPN1P2THRES		B43_PHY_OFDM(0xA4) | ||||
| #define B43_PHY_CCKSHIFTBITS_WA		B43_PHY_OFDM(0xA5)	/* CCK shiftbits workaround, FIXME rename */ | ||||
| #define B43_PHY_CCKSHIFTBITS		B43_PHY_OFDM(0xA7)	/* FIXME rename */ | ||||
| #define B43_PHY_DIVSRCHIDX		B43_PHY_OFDM(0xA8)	/* Divider search gain/index */ | ||||
| #define B43_PHY_CLIPP2THRES		B43_PHY_OFDM(0xA9) | ||||
| #define B43_PHY_CLIPP3THRES		B43_PHY_OFDM(0xAA) | ||||
| #define B43_PHY_DIVP1P2GAIN		B43_PHY_OFDM(0xAB) | ||||
| #define B43_PHY_DIVSRCHGAINBACK		B43_PHY_OFDM(0xAD)	/* Divider search gain back */ | ||||
| #define B43_PHY_DIVSRCHGAINCHNG		B43_PHY_OFDM(0xAE)	/* Divider search gain change */ | ||||
| #define B43_PHY_CRSTHRES1		B43_PHY_OFDM(0xC0)	/* CRS Threshold 1 (phy.rev >= 2 only) */ | ||||
| #define B43_PHY_CRSTHRES2		B43_PHY_OFDM(0xC1)	/* CRS Threshold 2 (phy.rev >= 2 only) */ | ||||
| #define B43_PHY_TSSIP_LTBASE		B43_PHY_OFDM(0x380)	/* TSSI power lookup table base */ | ||||
| #define B43_PHY_DC_LTBASE		B43_PHY_OFDM(0x3A0)	/* DC lookup table base */ | ||||
| #define B43_PHY_GAIN_LTBASE		B43_PHY_OFDM(0x3C0)	/* Gain lookup table base */ | ||||
| 
 | ||||
| /* CCK (B) PHY Registers */ | ||||
| #define B43_PHY_VERSION_CCK		B43_PHY_CCK(0x00)	/* Versioning register for B-PHY */ | ||||
| #define B43_PHY_CCKBBANDCFG		B43_PHY_CCK(0x01)	/* Contains antenna 0/1 control bit */ | ||||
| #define B43_PHY_PGACTL			B43_PHY_CCK(0x15)	/* PGA control */ | ||||
| #define  B43_PHY_PGACTL_LPF		0x1000	/* Low pass filter (?) */ | ||||
| #define  B43_PHY_PGACTL_LOWBANDW	0x0040	/* Low bandwidth flag */ | ||||
| #define  B43_PHY_PGACTL_UNKNOWN		0xEFA0 | ||||
| #define B43_PHY_FBCTL1			B43_PHY_CCK(0x18)	/* Frequency bandwidth control 1 */ | ||||
| #define B43_PHY_ITSSI			B43_PHY_CCK(0x29)	/* Idle TSSI */ | ||||
| #define B43_PHY_LO_LEAKAGE		B43_PHY_CCK(0x2D)	/* Measured LO leakage */ | ||||
| #define B43_PHY_ENERGY			B43_PHY_CCK(0x33)	/* Energy */ | ||||
| #define B43_PHY_SYNCCTL			B43_PHY_CCK(0x35) | ||||
| #define B43_PHY_FBCTL2			B43_PHY_CCK(0x38)	/* Frequency bandwidth control 2 */ | ||||
| #define B43_PHY_DACCTL			B43_PHY_CCK(0x60)	/* DAC control */ | ||||
| #define B43_PHY_RCCALOVER		B43_PHY_CCK(0x78)	/* RC calibration override */ | ||||
| 
 | ||||
| /* Extended G-PHY Registers */ | ||||
| #define B43_PHY_CLASSCTL		B43_PHY_EXTG(0x02)	/* Classify control */ | ||||
| #define B43_PHY_GTABCTL			B43_PHY_EXTG(0x03)	/* G-PHY table control (see below) */ | ||||
| #define  B43_PHY_GTABOFF		0x03FF	/* G-PHY table offset (see below) */ | ||||
| #define  B43_PHY_GTABNR			0xFC00	/* G-PHY table number (see below) */ | ||||
| #define  B43_PHY_GTABNR_SHIFT		10 | ||||
| #define B43_PHY_GTABDATA		B43_PHY_EXTG(0x04)	/* G-PHY table data */ | ||||
| #define B43_PHY_LO_MASK			B43_PHY_EXTG(0x0F)	/* Local Oscillator control mask */ | ||||
| #define B43_PHY_LO_CTL			B43_PHY_EXTG(0x10)	/* Local Oscillator control */ | ||||
| #define B43_PHY_RFOVER			B43_PHY_EXTG(0x11)	/* RF override */ | ||||
| #define B43_PHY_RFOVERVAL		B43_PHY_EXTG(0x12)	/* RF override value */ | ||||
| #define  B43_PHY_RFOVERVAL_EXTLNA	0x8000 | ||||
| #define  B43_PHY_RFOVERVAL_LNA		0x7000 | ||||
| #define  B43_PHY_RFOVERVAL_LNA_SHIFT	12 | ||||
| #define  B43_PHY_RFOVERVAL_PGA		0x0F00 | ||||
| #define  B43_PHY_RFOVERVAL_PGA_SHIFT	8 | ||||
| #define  B43_PHY_RFOVERVAL_UNK		0x0010	/* Unknown, always set. */ | ||||
| #define  B43_PHY_RFOVERVAL_TRSWRX	0x00E0 | ||||
| #define  B43_PHY_RFOVERVAL_BW		0x0003	/* Bandwidth flags */ | ||||
| #define   B43_PHY_RFOVERVAL_BW_LPF	0x0001	/* Low Pass Filter */ | ||||
| #define   B43_PHY_RFOVERVAL_BW_LBW	0x0002	/* Low Bandwidth (when set), high when unset */ | ||||
| #define B43_PHY_ANALOGOVER		B43_PHY_EXTG(0x14)	/* Analog override */ | ||||
| #define B43_PHY_ANALOGOVERVAL		B43_PHY_EXTG(0x15)	/* Analog override value */ | ||||
| 
 | ||||
| /*** OFDM table numbers ***/ | ||||
| #define B43_OFDMTAB(number, offset)	(((number) << B43_PHY_OTABLENR_SHIFT) | (offset)) | ||||
| #define B43_OFDMTAB_AGC1		B43_OFDMTAB(0x00, 0) | ||||
| #define B43_OFDMTAB_GAIN0		B43_OFDMTAB(0x00, 0) | ||||
| #define B43_OFDMTAB_GAINX		B43_OFDMTAB(0x01, 0)	//TODO rename
 | ||||
| #define B43_OFDMTAB_GAIN1		B43_OFDMTAB(0x01, 4) | ||||
| #define B43_OFDMTAB_AGC3		B43_OFDMTAB(0x02, 0) | ||||
| #define B43_OFDMTAB_GAIN2		B43_OFDMTAB(0x02, 3) | ||||
| #define B43_OFDMTAB_LNAHPFGAIN1		B43_OFDMTAB(0x03, 0) | ||||
| #define B43_OFDMTAB_WRSSI		B43_OFDMTAB(0x04, 0) | ||||
| #define B43_OFDMTAB_LNAHPFGAIN2		B43_OFDMTAB(0x04, 0) | ||||
| #define B43_OFDMTAB_NOISESCALE		B43_OFDMTAB(0x05, 0) | ||||
| #define B43_OFDMTAB_AGC2		B43_OFDMTAB(0x06, 0) | ||||
| #define B43_OFDMTAB_ROTOR		B43_OFDMTAB(0x08, 0) | ||||
| #define B43_OFDMTAB_ADVRETARD		B43_OFDMTAB(0x09, 0) | ||||
| #define B43_OFDMTAB_DAC			B43_OFDMTAB(0x0C, 0) | ||||
| #define B43_OFDMTAB_DC			B43_OFDMTAB(0x0E, 7) | ||||
| #define B43_OFDMTAB_PWRDYN2		B43_OFDMTAB(0x0E, 12) | ||||
| #define B43_OFDMTAB_LNAGAIN		B43_OFDMTAB(0x0E, 13) | ||||
| #define B43_OFDMTAB_UNKNOWN_0F		B43_OFDMTAB(0x0F, 0)	//TODO rename
 | ||||
| #define B43_OFDMTAB_UNKNOWN_APHY	B43_OFDMTAB(0x0F, 7)	//TODO rename
 | ||||
| #define B43_OFDMTAB_LPFGAIN		B43_OFDMTAB(0x0F, 12) | ||||
| #define B43_OFDMTAB_RSSI		B43_OFDMTAB(0x10, 0) | ||||
| #define B43_OFDMTAB_UNKNOWN_11		B43_OFDMTAB(0x11, 4)	//TODO rename
 | ||||
| #define B43_OFDMTAB_AGC1_R1		B43_OFDMTAB(0x13, 0) | ||||
| #define B43_OFDMTAB_GAINX_R1		B43_OFDMTAB(0x14, 0)	//TODO remove!
 | ||||
| #define B43_OFDMTAB_MINSIGSQ		B43_OFDMTAB(0x14, 0) | ||||
| #define B43_OFDMTAB_AGC3_R1		B43_OFDMTAB(0x15, 0) | ||||
| #define B43_OFDMTAB_WRSSI_R1		B43_OFDMTAB(0x15, 4) | ||||
| #define B43_OFDMTAB_TSSI		B43_OFDMTAB(0x15, 0) | ||||
| #define B43_OFDMTAB_DACRFPABB		B43_OFDMTAB(0x16, 0) | ||||
| #define B43_OFDMTAB_DACOFF		B43_OFDMTAB(0x17, 0) | ||||
| #define B43_OFDMTAB_DCBIAS		B43_OFDMTAB(0x18, 0) | ||||
| 
 | ||||
| u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset); | ||||
| void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u16 value); | ||||
| u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset); | ||||
| void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u32 value); | ||||
| 
 | ||||
| /*** G-PHY table numbers */ | ||||
| #define B43_GTAB(number, offset)	(((number) << B43_PHY_GTABNR_SHIFT) | (offset)) | ||||
| #define B43_GTAB_NRSSI			B43_GTAB(0x00, 0) | ||||
| #define B43_GTAB_TRFEMW			B43_GTAB(0x0C, 0x120) | ||||
| #define B43_GTAB_ORIGTR			B43_GTAB(0x2E, 0x298) | ||||
| 
 | ||||
| u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset);	//TODO implement
 | ||||
| void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value);	//TODO implement
 | ||||
| 
 | ||||
| #define B43_DEFAULT_CHANNEL_A	36 | ||||
| #define B43_DEFAULT_CHANNEL_BG	6 | ||||
| 
 | ||||
| enum { | ||||
| 	B43_ANTENNA0,		/* Antenna 0 */ | ||||
| 	B43_ANTENNA1,		/* Antenna 0 */ | ||||
| 	B43_ANTENNA_AUTO1,	/* Automatic, starting with antenna 1 */ | ||||
| 	B43_ANTENNA_AUTO0,	/* Automatic, starting with antenna 0 */ | ||||
| 	B43_ANTENNA2, | ||||
| 	B43_ANTENNA3 = 8, | ||||
| 
 | ||||
| 	B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, | ||||
| 	B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
| 	B43_INTERFMODE_NONE, | ||||
| 	B43_INTERFMODE_NONWLAN, | ||||
| 	B43_INTERFMODE_MANUALWLAN, | ||||
| 	B43_INTERFMODE_AUTOWLAN, | ||||
| }; | ||||
| 
 | ||||
| /* Masks for the different PHY versioning registers. */ | ||||
| #define B43_PHYVER_ANALOG		0xF000 | ||||
| #define B43_PHYVER_ANALOG_SHIFT		12 | ||||
| #define B43_PHYVER_TYPE			0x0F00 | ||||
| #define B43_PHYVER_TYPE_SHIFT		8 | ||||
| #define B43_PHYVER_VERSION		0x00FF | ||||
| 
 | ||||
| void b43_phy_lock(struct b43_wldev *dev); | ||||
| void b43_phy_unlock(struct b43_wldev *dev); | ||||
| 
 | ||||
| 
 | ||||
| /* Read a value from a PHY register */ | ||||
| u16 b43_phy_read(struct b43_wldev *dev, u16 offset); | ||||
| /* Write a value to a PHY register */ | ||||
| void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val); | ||||
| /* Mask a PHY register with a mask */ | ||||
| void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||||
| /* OR a PHY register with a bitmap */ | ||||
| void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set); | ||||
| /* Mask and OR a PHY register with a mask and bitmap */ | ||||
| void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||||
| 
 | ||||
| 
 | ||||
| int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_phy_early_init(struct b43_wldev *dev); | ||||
| int b43_phy_init(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); | ||||
| 
 | ||||
| void b43_phy_xmitpower(struct b43_wldev *dev); | ||||
| 
 | ||||
| /* Returns the boolean whether the board has HardwarePowerControl */ | ||||
| bool b43_has_hardware_pctl(struct b43_phy *phy); | ||||
| /* Returns the boolean whether "TX Magnification" is enabled. */ | ||||
| #define has_tx_magnification(phy) \ | ||||
| 	(((phy)->rev >= 2) &&			\ | ||||
| 	 ((phy)->radio_ver == 0x2050) &&	\ | ||||
| 	 ((phy)->radio_rev == 8)) | ||||
| /* Card uses the loopback gain stuff */ | ||||
| #define has_loopback_gain(phy) \ | ||||
| 	(((phy)->rev > 1) || ((phy)->gmode)) | ||||
| 
 | ||||
| /* Radio Attenuation (RF Attenuation) */ | ||||
| struct b43_rfatt { | ||||
| 	u8 att;			/* Attenuation value */ | ||||
| 	bool with_padmix;	/* Flag, PAD Mixer enabled. */ | ||||
| }; | ||||
| struct b43_rfatt_list { | ||||
| 	/* Attenuation values list */ | ||||
| 	const struct b43_rfatt *list; | ||||
| 	u8 len; | ||||
| 	/* Minimum/Maximum attenuation values */ | ||||
| 	u8 min_val; | ||||
| 	u8 max_val; | ||||
| }; | ||||
| 
 | ||||
| /* Returns true, if the values are the same. */ | ||||
| static inline bool b43_compare_rfatt(const struct b43_rfatt *a, | ||||
| 				     const struct b43_rfatt *b) | ||||
| { | ||||
| 	return ((a->att == b->att) && | ||||
| 		(a->with_padmix == b->with_padmix)); | ||||
| } | ||||
| 
 | ||||
| /* Baseband Attenuation */ | ||||
| struct b43_bbatt { | ||||
| 	u8 att;			/* Attenuation value */ | ||||
| }; | ||||
| struct b43_bbatt_list { | ||||
| 	/* Attenuation values list */ | ||||
| 	const struct b43_bbatt *list; | ||||
| 	u8 len; | ||||
| 	/* Minimum/Maximum attenuation values */ | ||||
| 	u8 min_val; | ||||
| 	u8 max_val; | ||||
| }; | ||||
| 
 | ||||
| /* Returns true, if the values are the same. */ | ||||
| static inline bool b43_compare_bbatt(const struct b43_bbatt *a, | ||||
| 				     const struct b43_bbatt *b) | ||||
| { | ||||
| 	return (a->att == b->att); | ||||
| } | ||||
| 
 | ||||
| /* tx_control bits. */ | ||||
| #define B43_TXCTL_PA3DB		0x40	/* PA Gain 3dB */ | ||||
| #define B43_TXCTL_PA2DB		0x20	/* PA Gain 2dB */ | ||||
| #define B43_TXCTL_TXMIX		0x10	/* TX Mixer Gain */ | ||||
| 
 | ||||
| /* Write BasebandAttenuation value to the device. */ | ||||
| void b43_phy_set_baseband_attenuation(struct b43_wldev *dev, | ||||
| 				      u16 baseband_attenuation); | ||||
| 
 | ||||
| extern const u8 b43_radio_channel_codes_bg[]; | ||||
| 
 | ||||
| void b43_radio_lock(struct b43_wldev *dev); | ||||
| void b43_radio_unlock(struct b43_wldev *dev); | ||||
| 
 | ||||
| 
 | ||||
| /* Read a value from a 16bit radio register */ | ||||
| u16 b43_radio_read16(struct b43_wldev *dev, u16 offset); | ||||
| /* Write a value to a 16bit radio register */ | ||||
| void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val); | ||||
| /* Mask a 16bit radio register with a mask */ | ||||
| void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||||
| /* OR a 16bit radio register with a bitmap */ | ||||
| void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); | ||||
| /* Mask and OR a PHY register with a mask and bitmap */ | ||||
| void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||||
| 
 | ||||
| 
 | ||||
| u16 b43_radio_init2050(struct b43_wldev *dev); | ||||
| void b43_radio_init2060(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_radio_turn_on(struct b43_wldev *dev); | ||||
| void b43_radio_turn_off(struct b43_wldev *dev, bool force); | ||||
| 
 | ||||
| int b43_radio_selectchannel(struct b43_wldev *dev, u8 channel, | ||||
| 			    int synthetic_pu_workaround); | ||||
| 
 | ||||
| u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel); | ||||
| u8 b43_radio_aci_scan(struct b43_wldev *dev); | ||||
| 
 | ||||
| int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode); | ||||
| 
 | ||||
| void b43_calc_nrssi_slope(struct b43_wldev *dev); | ||||
| void b43_calc_nrssi_threshold(struct b43_wldev *dev); | ||||
| s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset); | ||||
| void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val); | ||||
| void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val); | ||||
| void b43_nrssi_mem_update(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_radio_set_tx_iq(struct b43_wldev *dev); | ||||
| u16 b43_radio_calibrationvalue(struct b43_wldev *dev); | ||||
| 
 | ||||
| void b43_put_attenuation_into_ranges(struct b43_wldev *dev, | ||||
| 				     int *_bbatt, int *_rfatt); | ||||
| 
 | ||||
| void b43_set_txpower_g(struct b43_wldev *dev, | ||||
| 		       const struct b43_bbatt *bbatt, | ||||
| 		       const struct b43_rfatt *rfatt, u8 tx_control); | ||||
| 
 | ||||
| #endif /* B43_PHY_H_ */ | ||||
							
								
								
									
										536
									
								
								drivers/net/wireless/b43/phy_a.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										536
									
								
								drivers/net/wireless/b43/phy_a.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,536 @@ | ||||
| /*
 | ||||
| 
 | ||||
|   Broadcom B43 wireless driver | ||||
|   IEEE 802.11a PHY driver | ||||
| 
 | ||||
|   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, | ||||
|   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> | ||||
|   Copyright (c) 2005-2008 Michael Buesch <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 "b43.h" | ||||
| #include "phy_a.h" | ||||
| #include "phy_common.h" | ||||
| #include "wa.h" | ||||
| #include "tables.h" | ||||
| #include "main.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Get the freq, as it has to be written to the device. */ | ||||
| static inline u16 channel2freq_a(u8 channel) | ||||
| { | ||||
| 	B43_WARN_ON(channel > 200); | ||||
| 
 | ||||
| 	return (5000 + 5 * channel); | ||||
| } | ||||
| 
 | ||||
| static inline u16 freq_r3A_value(u16 frequency) | ||||
| { | ||||
| 	u16 value; | ||||
| 
 | ||||
| 	if (frequency < 5091) | ||||
| 		value = 0x0040; | ||||
| 	else if (frequency < 5321) | ||||
| 		value = 0x0000; | ||||
| 	else if (frequency < 5806) | ||||
| 		value = 0x0080; | ||||
| 	else | ||||
| 		value = 0x0040; | ||||
| 
 | ||||
| 	return value; | ||||
| } | ||||
| 
 | ||||
| void b43_radio_set_tx_iq(struct b43_wldev *dev) | ||||
| { | ||||
| 	static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; | ||||
| 	static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; | ||||
| 	u16 tmp = b43_radio_read16(dev, 0x001E); | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	for (i = 0; i < 5; i++) { | ||||
| 		for (j = 0; j < 5; j++) { | ||||
| 			if (tmp == (data_high[i] << 4 | data_low[j])) { | ||||
| 				b43_phy_write(dev, 0x0069, | ||||
| 					      (i - j) << 8 | 0x00C0); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||||
| { | ||||
| 	u16 freq, r8, tmp; | ||||
| 
 | ||||
| 	freq = channel2freq_a(channel); | ||||
| 
 | ||||
| 	r8 = b43_radio_read16(dev, 0x0008); | ||||
| 	b43_write16(dev, 0x03F0, freq); | ||||
| 	b43_radio_write16(dev, 0x0008, r8); | ||||
| 
 | ||||
| 	//TODO: write max channel TX power? to Radio 0x2D
 | ||||
| 	tmp = b43_radio_read16(dev, 0x002E); | ||||
| 	tmp &= 0x0080; | ||||
| 	//TODO: OR tmp with the Power out estimation for this channel?
 | ||||
| 	b43_radio_write16(dev, 0x002E, tmp); | ||||
| 
 | ||||
| 	if (freq >= 4920 && freq <= 5500) { | ||||
| 		/*
 | ||||
| 		 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; | ||||
| 		 *    = (freq * 0.025862069 | ||||
| 		 */ | ||||
| 		r8 = 3 * freq / 116;	/* is equal to r8 = freq * 0.025862 */ | ||||
| 	} | ||||
| 	b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); | ||||
| 	b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); | ||||
| 	b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); | ||||
| 	b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022) | ||||
| 					& 0x000F) | (r8 << 4)); | ||||
| 	b43_radio_write16(dev, 0x002A, (r8 << 4)); | ||||
| 	b43_radio_write16(dev, 0x002B, (r8 << 4)); | ||||
| 	b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008) | ||||
| 					& 0x00F0) | (r8 << 4)); | ||||
| 	b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029) | ||||
| 					& 0xFF0F) | 0x00B0); | ||||
| 	b43_radio_write16(dev, 0x0035, 0x00AA); | ||||
| 	b43_radio_write16(dev, 0x0036, 0x0085); | ||||
| 	b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A) | ||||
| 					& 0xFF20) | | ||||
| 			  freq_r3A_value(freq)); | ||||
| 	b43_radio_write16(dev, 0x003D, | ||||
| 			  b43_radio_read16(dev, 0x003D) & 0x00FF); | ||||
| 	b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081) | ||||
| 					& 0xFF7F) | 0x0080); | ||||
| 	b43_radio_write16(dev, 0x0035, | ||||
| 			  b43_radio_read16(dev, 0x0035) & 0xFFEF); | ||||
| 	b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035) | ||||
| 					& 0xFFEF) | 0x0010); | ||||
| 	b43_radio_set_tx_iq(dev); | ||||
| 	//TODO: TSSI2dbm workaround
 | ||||
| //FIXME	b43_phy_xmitpower(dev);
 | ||||
| } | ||||
| 
 | ||||
| void b43_radio_init2060(struct b43_wldev *dev) | ||||
| { | ||||
| 	b43_radio_write16(dev, 0x0004, 0x00C0); | ||||
| 	b43_radio_write16(dev, 0x0005, 0x0008); | ||||
| 	b43_radio_write16(dev, 0x0009, 0x0040); | ||||
| 	b43_radio_write16(dev, 0x0005, 0x00AA); | ||||
| 	b43_radio_write16(dev, 0x0032, 0x008F); | ||||
| 	b43_radio_write16(dev, 0x0006, 0x008F); | ||||
| 	b43_radio_write16(dev, 0x0034, 0x008F); | ||||
| 	b43_radio_write16(dev, 0x002C, 0x0007); | ||||
| 	b43_radio_write16(dev, 0x0082, 0x0080); | ||||
| 	b43_radio_write16(dev, 0x0080, 0x0000); | ||||
| 	b43_radio_write16(dev, 0x003F, 0x00DA); | ||||
| 	b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||||
| 	b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010); | ||||
| 	b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||||
| 	b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||||
| 	msleep(1);		/* delay 400usec */ | ||||
| 
 | ||||
| 	b43_radio_write16(dev, 0x0081, | ||||
| 			  (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010); | ||||
| 	msleep(1);		/* delay 400usec */ | ||||
| 
 | ||||
| 	b43_radio_write16(dev, 0x0005, | ||||
| 			  (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008); | ||||
| 	b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010); | ||||
| 	b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||||
| 	b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040); | ||||
| 	b43_radio_write16(dev, 0x0081, | ||||
| 			  (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040); | ||||
| 	b43_radio_write16(dev, 0x0005, | ||||
| 			  (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008); | ||||
| 	b43_phy_write(dev, 0x0063, 0xDDC6); | ||||
| 	b43_phy_write(dev, 0x0069, 0x07BE); | ||||
| 	b43_phy_write(dev, 0x006A, 0x0000); | ||||
| 
 | ||||
| 	aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev)); | ||||
| 
 | ||||
| 	msleep(1); | ||||
| } | ||||
| 
 | ||||
| static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (dev->phy.rev < 3) { | ||||
| 		if (enable) | ||||
| 			for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8); | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_WRSSI, i, 0xFFF8); | ||||
| 			} | ||||
| 		else | ||||
| 			for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]); | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]); | ||||
| 			} | ||||
| 	} else { | ||||
| 		if (enable) | ||||
| 			for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_WRSSI, i, 0x0820); | ||||
| 		else | ||||
| 			for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++) | ||||
| 				b43_ofdmtab_write16(dev, | ||||
| 					B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void b43_phy_ww(struct b43_wldev *dev) | ||||
| { | ||||
| 	u16 b, curr_s, best_s = 0xFFFF; | ||||
| 	int i; | ||||
| 
 | ||||
| 	b43_phy_write(dev, B43_PHY_CRS0, | ||||
| 		b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||||
| 		b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0x82), | ||||
| 		(b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300); | ||||
| 	b43_radio_write16(dev, 0x0009, | ||||
| 		b43_radio_read16(dev, 0x0009) | 0x0080); | ||||
| 	b43_radio_write16(dev, 0x0012, | ||||
| 		(b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002); | ||||
| 	b43_wa_initgains(dev); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5); | ||||
| 	b = b43_phy_read(dev, B43_PHY_PWRDOWN); | ||||
| 	b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005); | ||||
| 	b43_radio_write16(dev, 0x0004, | ||||
| 		b43_radio_read16(dev, 0x0004) | 0x0004); | ||||
| 	for (i = 0x10; i <= 0x20; i++) { | ||||
| 		b43_radio_write16(dev, 0x0013, i); | ||||
| 		curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF; | ||||
| 		if (!curr_s) { | ||||
| 			best_s = 0x0000; | ||||
| 			break; | ||||
| 		} else if (curr_s >= 0x0080) | ||||
| 			curr_s = 0x0100 - curr_s; | ||||
| 		if (curr_s < best_s) | ||||
| 			best_s = curr_s; | ||||
| 	} | ||||
| 	b43_phy_write(dev, B43_PHY_PWRDOWN, b); | ||||
| 	b43_radio_write16(dev, 0x0004, | ||||
| 		b43_radio_read16(dev, 0x0004) & 0xFFFB); | ||||
| 	b43_radio_write16(dev, 0x0013, best_s); | ||||
| 	b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0xBB), | ||||
| 		(b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM61, | ||||
| 		(b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0x13), | ||||
| 		(b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0x14), | ||||
| 		(b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000); | ||||
| 	b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017); | ||||
| 	for (i = 0; i < 6; i++) | ||||
| 		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F); | ||||
| 	b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E); | ||||
| 	b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011); | ||||
| 	b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013); | ||||
| 	b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030); | ||||
| 	b43_phy_write(dev, B43_PHY_CRS0, | ||||
| 		b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||||
| } | ||||
| 
 | ||||
| static void hardware_pctl_init_aphy(struct b43_wldev *dev) | ||||
| { | ||||
| 	//TODO
 | ||||
| } | ||||
| 
 | ||||
| void b43_phy_inita(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct ssb_bus *bus = dev->dev->bus; | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 
 | ||||
| 	/* This lowlevel A-PHY init is also called from G-PHY init.
 | ||||
| 	 * So we must not access phy->a, if called from G-PHY code. | ||||
| 	 */ | ||||
| 	B43_WARN_ON((phy->type != B43_PHYTYPE_A) && | ||||
| 		    (phy->type != B43_PHYTYPE_G)); | ||||
| 
 | ||||
| 	might_sleep(); | ||||
| 
 | ||||
| 	if (phy->rev >= 6) { | ||||
| 		if (phy->type == B43_PHYTYPE_A) | ||||
| 			b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||||
| 				b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000); | ||||
| 		if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) | ||||
| 			b43_phy_write(dev, B43_PHY_ENCORE, | ||||
| 				b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010); | ||||
| 		else | ||||
| 			b43_phy_write(dev, B43_PHY_ENCORE, | ||||
| 				b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010); | ||||
| 	} | ||||
| 
 | ||||
| 	b43_wa_all(dev); | ||||
| 
 | ||||
| 	if (phy->type == B43_PHYTYPE_A) { | ||||
| 		if (phy->gmode && (phy->rev < 3)) | ||||
| 			b43_phy_write(dev, 0x0034, | ||||
| 				b43_phy_read(dev, 0x0034) | 0x0001); | ||||
| 		b43_phy_rssiagc(dev, 0); | ||||
| 
 | ||||
| 		b43_phy_write(dev, B43_PHY_CRS0, | ||||
| 			b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||||
| 
 | ||||
| 		b43_radio_init2060(dev); | ||||
| 
 | ||||
| 		if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||||
| 		    ((bus->boardinfo.type == SSB_BOARD_BU4306) || | ||||
| 		     (bus->boardinfo.type == SSB_BOARD_BU4309))) { | ||||
| 			; //TODO: A PHY LO
 | ||||
| 		} | ||||
| 
 | ||||
| 		if (phy->rev >= 3) | ||||
| 			b43_phy_ww(dev); | ||||
| 
 | ||||
| 		hardware_pctl_init_aphy(dev); | ||||
| 
 | ||||
| 		//TODO: radar detection
 | ||||
| 	} | ||||
| 
 | ||||
| 	if ((phy->type == B43_PHYTYPE_G) && | ||||
| 	    (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { | ||||
| 		b43_phy_write(dev, B43_PHY_OFDM(0x6E), | ||||
| 				  (b43_phy_read(dev, B43_PHY_OFDM(0x6E)) | ||||
| 				   & 0xE000) | 0x3CF); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int b43_aphy_op_allocate(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_a *aphy; | ||||
| 
 | ||||
| 	aphy = kzalloc(sizeof(*aphy), GFP_KERNEL); | ||||
| 	if (!aphy) | ||||
| 		return -ENOMEM; | ||||
| 	dev->phy.a = aphy; | ||||
| 
 | ||||
| 	//TODO init struct b43_phy_a
 | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int b43_aphy_op_init(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_a *aphy = dev->phy.a; | ||||
| 
 | ||||
| 	b43_phy_inita(dev); | ||||
| 	aphy->initialised = 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_exit(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy_a *aphy = dev->phy.a; | ||||
| 
 | ||||
| 	if (aphy->initialised) { | ||||
| 		//TODO
 | ||||
| 		aphy->initialised = 0; | ||||
| 	} | ||||
| 	//TODO
 | ||||
| 	kfree(aphy); | ||||
| 	dev->phy.a = NULL; | ||||
| } | ||||
| 
 | ||||
| static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) | ||||
| { | ||||
| 	/* OFDM registers are base-registers for the A-PHY. */ | ||||
| 	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { | ||||
| 		offset &= ~B43_PHYROUTE; | ||||
| 		offset |= B43_PHYROUTE_BASE; | ||||
| 	} | ||||
| 
 | ||||
| #if B43_DEBUG | ||||
| 	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { | ||||
| 		/* Ext-G registers are only available on G-PHYs */ | ||||
| 		b43err(dev->wl, "Invalid EXT-G PHY access at " | ||||
| 		       "0x%04X on A-PHY\n", offset); | ||||
| 		dump_stack(); | ||||
| 	} | ||||
| 	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) { | ||||
| 		/* N-BMODE registers are only available on N-PHYs */ | ||||
| 		b43err(dev->wl, "Invalid N-BMODE PHY access at " | ||||
| 		       "0x%04X on A-PHY\n", offset); | ||||
| 		dump_stack(); | ||||
| 	} | ||||
| #endif /* B43_DEBUG */ | ||||
| 
 | ||||
| 	return offset; | ||||
| } | ||||
| 
 | ||||
| static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	reg = adjust_phyreg(dev, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||||
| 	return b43_read16(dev, B43_MMIO_PHY_DATA); | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	reg = adjust_phyreg(dev, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||||
| 	b43_write16(dev, B43_MMIO_PHY_DATA, value); | ||||
| } | ||||
| 
 | ||||
| static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	/* Register 1 is a 32-bit register. */ | ||||
| 	B43_WARN_ON(reg == 1); | ||||
| 	/* A-PHY needs 0x40 for read access */ | ||||
| 	reg |= 0x40; | ||||
| 
 | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||||
| 	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	/* Register 1 is a 32-bit register. */ | ||||
| 	B43_WARN_ON(reg == 1); | ||||
| 
 | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||||
| 	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | ||||
| } | ||||
| 
 | ||||
| static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev) | ||||
| { | ||||
| 	return (dev->phy.rev >= 5); | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, | ||||
| 					enum rfkill_state state) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| static int b43_aphy_op_switch_channel(struct b43_wldev *dev, | ||||
| 				      unsigned int new_channel) | ||||
| { | ||||
| 	if (new_channel > 200) | ||||
| 		return -EINVAL; | ||||
| 	aphy_channel_switch(dev, new_channel); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev) | ||||
| { | ||||
| 	return 36; /* Default to channel 36 */ | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) | ||||
| {//TODO
 | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	u64 hf; | ||||
| 	u16 tmp; | ||||
| 	int autodiv = 0; | ||||
| 
 | ||||
| 	if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) | ||||
| 		autodiv = 1; | ||||
| 
 | ||||
| 	hf = b43_hf_read(dev); | ||||
| 	hf &= ~B43_HF_ANTDIVHELP; | ||||
| 	b43_hf_write(dev, hf); | ||||
| 
 | ||||
| 	tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); | ||||
| 	tmp &= ~B43_PHY_BBANDCFG_RXANT; | ||||
| 	tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) | ||||
| 	    << B43_PHY_BBANDCFG_RXANT_SHIFT; | ||||
| 	b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); | ||||
| 
 | ||||
| 	if (autodiv) { | ||||
| 		tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||||
| 		if (antenna == B43_ANTENNA_AUTO0) | ||||
| 			tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; | ||||
| 		else | ||||
| 			tmp |= B43_PHY_ANTDWELL_AUTODIV1; | ||||
| 		b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||||
| 	} | ||||
| 	if (phy->rev < 3) { | ||||
| 		tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||||
| 		tmp = (tmp & 0xFF00) | 0x24; | ||||
| 		b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||||
| 	} else { | ||||
| 		tmp = b43_phy_read(dev, B43_PHY_OFDM61); | ||||
| 		tmp |= 0x10; | ||||
| 		b43_phy_write(dev, B43_PHY_OFDM61, tmp); | ||||
| 		if (phy->analog == 3) { | ||||
| 			b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||||
| 				      0x1D); | ||||
| 			b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||||
| 				      8); | ||||
| 		} else { | ||||
| 			b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||||
| 				      0x3A); | ||||
| 			tmp = | ||||
| 			    b43_phy_read(dev, | ||||
| 					 B43_PHY_ADIVRELATED); | ||||
| 			tmp = (tmp & 0xFF00) | 8; | ||||
| 			b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||||
| 				      tmp); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	hf |= B43_HF_ANTDIVHELP; | ||||
| 	b43_hf_write(dev, hf); | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_xmitpower(struct b43_wldev *dev) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev) | ||||
| {//TODO
 | ||||
| } | ||||
| 
 | ||||
| const struct b43_phy_operations b43_phyops_a = { | ||||
| 	.allocate		= b43_aphy_op_allocate, | ||||
| 	.init			= b43_aphy_op_init, | ||||
| 	.exit			= b43_aphy_op_exit, | ||||
| 	.phy_read		= b43_aphy_op_read, | ||||
| 	.phy_write		= b43_aphy_op_write, | ||||
| 	.radio_read		= b43_aphy_op_radio_read, | ||||
| 	.radio_write		= b43_aphy_op_radio_write, | ||||
| 	.supports_hwpctl	= b43_aphy_op_supports_hwpctl, | ||||
| 	.software_rfkill	= b43_aphy_op_software_rfkill, | ||||
| 	.switch_channel		= b43_aphy_op_switch_channel, | ||||
| 	.get_default_chan	= b43_aphy_op_get_default_chan, | ||||
| 	.set_rx_antenna		= b43_aphy_op_set_rx_antenna, | ||||
| 	.xmitpower		= b43_aphy_op_xmitpower, | ||||
| 	.pwork_15sec		= b43_aphy_op_pwork_15sec, | ||||
| 	.pwork_60sec		= b43_aphy_op_pwork_60sec, | ||||
| }; | ||||
							
								
								
									
										124
									
								
								drivers/net/wireless/b43/phy_a.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								drivers/net/wireless/b43/phy_a.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | ||||
| #ifndef LINUX_B43_PHY_A_H_ | ||||
| #define LINUX_B43_PHY_A_H_ | ||||
| 
 | ||||
| #include "phy_common.h" | ||||
| 
 | ||||
| 
 | ||||
| /* OFDM (A) PHY Registers */ | ||||
| #define B43_PHY_VERSION_OFDM		B43_PHY_OFDM(0x00)	/* Versioning register for A-PHY */ | ||||
| #define B43_PHY_BBANDCFG		B43_PHY_OFDM(0x01)	/* Baseband config */ | ||||
| #define  B43_PHY_BBANDCFG_RXANT		0x180	/* RX Antenna selection */ | ||||
| #define  B43_PHY_BBANDCFG_RXANT_SHIFT	7 | ||||
| #define B43_PHY_PWRDOWN			B43_PHY_OFDM(0x03)	/* Powerdown */ | ||||
| #define B43_PHY_CRSTHRES1_R1		B43_PHY_OFDM(0x06)	/* CRS Threshold 1 (phy.rev 1 only) */ | ||||
| #define B43_PHY_LNAHPFCTL		B43_PHY_OFDM(0x1C)	/* LNA/HPF control */ | ||||
| #define B43_PHY_LPFGAINCTL		B43_PHY_OFDM(0x20)	/* LPF Gain control */ | ||||
| #define B43_PHY_ADIVRELATED		B43_PHY_OFDM(0x27)	/* FIXME rename */ | ||||
| #define B43_PHY_CRS0			B43_PHY_OFDM(0x29) | ||||
| #define  B43_PHY_CRS0_EN		0x4000 | ||||
| #define B43_PHY_PEAK_COUNT		B43_PHY_OFDM(0x30) | ||||
| #define B43_PHY_ANTDWELL		B43_PHY_OFDM(0x2B)	/* Antenna dwell */ | ||||
| #define  B43_PHY_ANTDWELL_AUTODIV1	0x0100	/* Automatic RX diversity start antenna */ | ||||
| #define B43_PHY_ENCORE			B43_PHY_OFDM(0x49)	/* "Encore" (RangeMax / BroadRange) */ | ||||
| #define  B43_PHY_ENCORE_EN		0x0200	/* Encore enable */ | ||||
| #define B43_PHY_LMS			B43_PHY_OFDM(0x55) | ||||
| #define B43_PHY_OFDM61			B43_PHY_OFDM(0x61)	/* FIXME rename */ | ||||
| #define  B43_PHY_OFDM61_10		0x0010	/* FIXME rename */ | ||||
| #define B43_PHY_IQBAL			B43_PHY_OFDM(0x69)	/* I/Q balance */ | ||||
| #define B43_PHY_BBTXDC_BIAS		B43_PHY_OFDM(0x6B)	/* Baseband TX DC bias */ | ||||
| #define B43_PHY_OTABLECTL		B43_PHY_OFDM(0x72)	/* OFDM table control (see below) */ | ||||
| #define  B43_PHY_OTABLEOFF		0x03FF	/* OFDM table offset (see below) */ | ||||
| #define  B43_PHY_OTABLENR		0xFC00	/* OFDM table number (see below) */ | ||||
| #define  B43_PHY_OTABLENR_SHIFT		10 | ||||
| #define B43_PHY_OTABLEI			B43_PHY_OFDM(0x73)	/* OFDM table data I */ | ||||
| #define B43_PHY_OTABLEQ			B43_PHY_OFDM(0x74)	/* OFDM table data Q */ | ||||
| #define B43_PHY_HPWR_TSSICTL		B43_PHY_OFDM(0x78)	/* Hardware power TSSI control */ | ||||
| #define B43_PHY_ADCCTL			B43_PHY_OFDM(0x7A)	/* ADC control */ | ||||
| #define B43_PHY_IDLE_TSSI		B43_PHY_OFDM(0x7B) | ||||
| #define B43_PHY_A_TEMP_SENSE		B43_PHY_OFDM(0x7C)	/* A PHY temperature sense */ | ||||
| #define B43_PHY_NRSSITHRES		B43_PHY_OFDM(0x8A)	/* NRSSI threshold */ | ||||
| #define B43_PHY_ANTWRSETT		B43_PHY_OFDM(0x8C)	/* Antenna WR settle */ | ||||
| #define  B43_PHY_ANTWRSETT_ARXDIV	0x2000	/* Automatic RX diversity enabled */ | ||||
| #define B43_PHY_CLIPPWRDOWNT		B43_PHY_OFDM(0x93)	/* Clip powerdown threshold */ | ||||
| #define B43_PHY_OFDM9B			B43_PHY_OFDM(0x9B)	/* FIXME rename */ | ||||
| #define B43_PHY_N1P1GAIN		B43_PHY_OFDM(0xA0) | ||||
| #define B43_PHY_P1P2GAIN		B43_PHY_OFDM(0xA1) | ||||
| #define B43_PHY_N1N2GAIN		B43_PHY_OFDM(0xA2) | ||||
| #define B43_PHY_CLIPTHRES		B43_PHY_OFDM(0xA3) | ||||
| #define B43_PHY_CLIPN1P2THRES		B43_PHY_OFDM(0xA4) | ||||
| #define B43_PHY_CCKSHIFTBITS_WA		B43_PHY_OFDM(0xA5)	/* CCK shiftbits workaround, FIXME rename */ | ||||
| #define B43_PHY_CCKSHIFTBITS		B43_PHY_OFDM(0xA7)	/* FIXME rename */ | ||||
| #define B43_PHY_DIVSRCHIDX		B43_PHY_OFDM(0xA8)	/* Divider search gain/index */ | ||||
| #define B43_PHY_CLIPP2THRES		B43_PHY_OFDM(0xA9) | ||||
| #define B43_PHY_CLIPP3THRES		B43_PHY_OFDM(0xAA) | ||||
| #define B43_PHY_DIVP1P2GAIN		B43_PHY_OFDM(0xAB) | ||||
| #define B43_PHY_DIVSRCHGAINBACK		B43_PHY_OFDM(0xAD)	/* Divider search gain back */ | ||||
| #define B43_PHY_DIVSRCHGAINCHNG		B43_PHY_OFDM(0xAE)	/* Divider search gain change */ | ||||
| #define B43_PHY_CRSTHRES1		B43_PHY_OFDM(0xC0)	/* CRS Threshold 1 (phy.rev >= 2 only) */ | ||||
| #define B43_PHY_CRSTHRES2		B43_PHY_OFDM(0xC1)	/* CRS Threshold 2 (phy.rev >= 2 only) */ | ||||
| #define B43_PHY_TSSIP_LTBASE		B43_PHY_OFDM(0x380)	/* TSSI power lookup table base */ | ||||
| #define B43_PHY_DC_LTBASE		B43_PHY_OFDM(0x3A0)	/* DC lookup table base */ | ||||
| #define B43_PHY_GAIN_LTBASE		B43_PHY_OFDM(0x3C0)	/* Gain lookup table base */ | ||||
| 
 | ||||
| /*** OFDM table numbers ***/ | ||||
| #define B43_OFDMTAB(number, offset)	(((number) << B43_PHY_OTABLENR_SHIFT) | (offset)) | ||||
| #define B43_OFDMTAB_AGC1		B43_OFDMTAB(0x00, 0) | ||||
| #define B43_OFDMTAB_GAIN0		B43_OFDMTAB(0x00, 0) | ||||
| #define B43_OFDMTAB_GAINX		B43_OFDMTAB(0x01, 0)	//TODO rename
 | ||||
| #define B43_OFDMTAB_GAIN1		B43_OFDMTAB(0x01, 4) | ||||
| #define B43_OFDMTAB_AGC3		B43_OFDMTAB(0x02, 0) | ||||
| #define B43_OFDMTAB_GAIN2		B43_OFDMTAB(0x02, 3) | ||||
| #define B43_OFDMTAB_LNAHPFGAIN1		B43_OFDMTAB(0x03, 0) | ||||
| #define B43_OFDMTAB_WRSSI		B43_OFDMTAB(0x04, 0) | ||||
| #define B43_OFDMTAB_LNAHPFGAIN2		B43_OFDMTAB(0x04, 0) | ||||
| #define B43_OFDMTAB_NOISESCALE		B43_OFDMTAB(0x05, 0) | ||||
| #define B43_OFDMTAB_AGC2		B43_OFDMTAB(0x06, 0) | ||||
| #define B43_OFDMTAB_ROTOR		B43_OFDMTAB(0x08, 0) | ||||
| #define B43_OFDMTAB_ADVRETARD		B43_OFDMTAB(0x09, 0) | ||||
| #define B43_OFDMTAB_DAC			B43_OFDMTAB(0x0C, 0) | ||||
| #define B43_OFDMTAB_DC			B43_OFDMTAB(0x0E, 7) | ||||
| #define B43_OFDMTAB_PWRDYN2		B43_OFDMTAB(0x0E, 12) | ||||
| #define B43_OFDMTAB_LNAGAIN		B43_OFDMTAB(0x0E, 13) | ||||
| #define B43_OFDMTAB_UNKNOWN_0F		B43_OFDMTAB(0x0F, 0)	//TODO rename
 | ||||
| #define B43_OFDMTAB_UNKNOWN_APHY	B43_OFDMTAB(0x0F, 7)	//TODO rename
 | ||||
| #define B43_OFDMTAB_LPFGAIN		B43_OFDMTAB(0x0F, 12) | ||||
| #define B43_OFDMTAB_RSSI		B43_OFDMTAB(0x10, 0) | ||||
| #define B43_OFDMTAB_UNKNOWN_11		B43_OFDMTAB(0x11, 4)	//TODO rename
 | ||||
| #define B43_OFDMTAB_AGC1_R1		B43_OFDMTAB(0x13, 0) | ||||
| #define B43_OFDMTAB_GAINX_R1		B43_OFDMTAB(0x14, 0)	//TODO remove!
 | ||||
| #define B43_OFDMTAB_MINSIGSQ		B43_OFDMTAB(0x14, 0) | ||||
| #define B43_OFDMTAB_AGC3_R1		B43_OFDMTAB(0x15, 0) | ||||
| #define B43_OFDMTAB_WRSSI_R1		B43_OFDMTAB(0x15, 4) | ||||
| #define B43_OFDMTAB_TSSI		B43_OFDMTAB(0x15, 0) | ||||
| #define B43_OFDMTAB_DACRFPABB		B43_OFDMTAB(0x16, 0) | ||||
| #define B43_OFDMTAB_DACOFF		B43_OFDMTAB(0x17, 0) | ||||
| #define B43_OFDMTAB_DCBIAS		B43_OFDMTAB(0x18, 0) | ||||
| 
 | ||||
| u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset); | ||||
| void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u16 value); | ||||
| u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset); | ||||
| void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u32 value); | ||||
| 
 | ||||
| 
 | ||||
| struct b43_phy_a { | ||||
| 	bool initialised; | ||||
| 
 | ||||
| 	/* A-PHY TX Power control value. */ | ||||
| 	u16 txpwr_offset; | ||||
| 
 | ||||
| 	//TODO lots of missing stuff
 | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_inita - Lowlevel A-PHY init routine. | ||||
|  * This is _only_ used by the G-PHY code. | ||||
|  */ | ||||
| void b43_phy_inita(struct b43_wldev *dev); | ||||
| 
 | ||||
| 
 | ||||
| struct b43_phy_operations; | ||||
| extern const struct b43_phy_operations b43_phyops_a; | ||||
| 
 | ||||
| #endif /* LINUX_B43_PHY_A_H_ */ | ||||
							
								
								
									
										276
									
								
								drivers/net/wireless/b43/phy_common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								drivers/net/wireless/b43/phy_common.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,276 @@ | ||||
| /*
 | ||||
| 
 | ||||
|   Broadcom B43 wireless driver | ||||
|   Common PHY routines | ||||
| 
 | ||||
|   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, | ||||
|   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> | ||||
|   Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de> | ||||
|   Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org> | ||||
|   Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of the GNU General Public License as published by | ||||
|   the Free Software Foundation; either version 2 of the License, or | ||||
|   (at your option) any later version. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, | ||||
|   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|   GNU General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; see the file COPYING.  If not, write to | ||||
|   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | ||||
|   Boston, MA 02110-1301, USA. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #include "phy_common.h" | ||||
| #include "phy_g.h" | ||||
| #include "phy_a.h" | ||||
| #include "nphy.h" | ||||
| #include "b43.h" | ||||
| #include "main.h" | ||||
| 
 | ||||
| 
 | ||||
| int b43_phy_operations_setup(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &(dev->phy); | ||||
| 	int err; | ||||
| 
 | ||||
| 	phy->ops = NULL; | ||||
| 
 | ||||
| 	switch (phy->type) { | ||||
| 	case B43_PHYTYPE_A: | ||||
| 		phy->ops = &b43_phyops_a; | ||||
| 		break; | ||||
| 	case B43_PHYTYPE_G: | ||||
| 		phy->ops = &b43_phyops_g; | ||||
| 		break; | ||||
| 	case B43_PHYTYPE_N: | ||||
| #ifdef CONFIG_B43_NPHY | ||||
| 		phy->ops = &b43_phyops_n; | ||||
| #endif | ||||
| 		break; | ||||
| 	case B43_PHYTYPE_LP: | ||||
| 		/* FIXME: Not yet */ | ||||
| 		break; | ||||
| 	} | ||||
| 	if (B43_WARN_ON(!phy->ops)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	err = phy->ops->allocate(dev); | ||||
| 	if (err) | ||||
| 		phy->ops = NULL; | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| int b43_phy_init(struct b43_wldev *dev) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	const struct b43_phy_operations *ops = phy->ops; | ||||
| 	int err; | ||||
| 
 | ||||
| 	phy->channel = ops->get_default_chan(dev); | ||||
| 
 | ||||
| 	ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED); | ||||
| 	err = ops->init(dev); | ||||
| 	if (err) { | ||||
| 		b43err(dev->wl, "PHY init failed\n"); | ||||
| 		goto err_block_rf; | ||||
| 	} | ||||
| 	/* Make sure to switch hardware and firmware (SHM) to
 | ||||
| 	 * the default channel. */ | ||||
| 	err = b43_switch_channel(dev, ops->get_default_chan(dev)); | ||||
| 	if (err) { | ||||
| 		b43err(dev->wl, "PHY init: Channel switch to default failed\n"); | ||||
| 		goto err_phy_exit; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| err_phy_exit: | ||||
| 	if (ops->exit) | ||||
| 		ops->exit(dev); | ||||
| err_block_rf: | ||||
| 	ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| void b43_phy_exit(struct b43_wldev *dev) | ||||
| { | ||||
| 	const struct b43_phy_operations *ops = dev->phy.ops; | ||||
| 
 | ||||
| 	ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); | ||||
| 	if (ops->exit) | ||||
| 		ops->exit(dev); | ||||
| } | ||||
| 
 | ||||
| bool b43_has_hardware_pctl(struct b43_wldev *dev) | ||||
| { | ||||
| 	if (!dev->phy.hardware_power_control) | ||||
| 		return 0; | ||||
| 	if (!dev->phy.ops->supports_hwpctl) | ||||
| 		return 0; | ||||
| 	return dev->phy.ops->supports_hwpctl(dev); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_lock(struct b43_wldev *dev) | ||||
| { | ||||
| 	u32 macctl; | ||||
| 
 | ||||
| 	macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||||
| 	B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK); | ||||
| 	macctl |= B43_MACCTL_RADIOLOCK; | ||||
| 	b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||||
| 	/* Commit the write and wait for the device
 | ||||
| 	 * to exit any radio register access. */ | ||||
| 	b43_read32(dev, B43_MMIO_MACCTL); | ||||
| 	udelay(10); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_unlock(struct b43_wldev *dev) | ||||
| { | ||||
| 	u32 macctl; | ||||
| 
 | ||||
| 	/* Commit any write */ | ||||
| 	b43_read16(dev, B43_MMIO_PHY_VER); | ||||
| 	/* unlock */ | ||||
| 	macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||||
| 	B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK)); | ||||
| 	macctl &= ~B43_MACCTL_RADIOLOCK; | ||||
| 	b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_lock(struct b43_wldev *dev) | ||||
| { | ||||
| #if B43_DEBUG | ||||
| 	B43_WARN_ON(dev->phy.phy_locked); | ||||
| 	dev->phy.phy_locked = 1; | ||||
| #endif | ||||
| 	B43_WARN_ON(dev->dev->id.revision < 3); | ||||
| 
 | ||||
| 	if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||||
| 		b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_unlock(struct b43_wldev *dev) | ||||
| { | ||||
| #if B43_DEBUG | ||||
| 	B43_WARN_ON(!dev->phy.phy_locked); | ||||
| 	dev->phy.phy_locked = 0; | ||||
| #endif | ||||
| 	B43_WARN_ON(dev->dev->id.revision < 3); | ||||
| 
 | ||||
| 	if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||||
| 		b43_power_saving_ctl_bits(dev, 0); | ||||
| } | ||||
| 
 | ||||
| u16 b43_radio_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	return dev->phy.ops->radio_read(dev, reg); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	dev->phy.ops->radio_write(dev, reg, value); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||||
| { | ||||
| 	b43_radio_write16(dev, offset, | ||||
| 			  b43_radio_read16(dev, offset) & mask); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) | ||||
| { | ||||
| 	b43_radio_write16(dev, offset, | ||||
| 			  b43_radio_read16(dev, offset) | set); | ||||
| } | ||||
| 
 | ||||
| void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||||
| { | ||||
| 	b43_radio_write16(dev, offset, | ||||
| 			  (b43_radio_read16(dev, offset) & mask) | set); | ||||
| } | ||||
| 
 | ||||
| u16 b43_phy_read(struct b43_wldev *dev, u16 reg) | ||||
| { | ||||
| 	return dev->phy.ops->phy_read(dev, reg); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | ||||
| { | ||||
| 	dev->phy.ops->phy_write(dev, reg, value); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||||
| { | ||||
| 	b43_phy_write(dev, offset, | ||||
| 		      b43_phy_read(dev, offset) & mask); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) | ||||
| { | ||||
| 	b43_phy_write(dev, offset, | ||||
| 		      b43_phy_read(dev, offset) | set); | ||||
| } | ||||
| 
 | ||||
| void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||||
| { | ||||
| 	b43_phy_write(dev, offset, | ||||
| 		      (b43_phy_read(dev, offset) & mask) | set); | ||||
| } | ||||
| 
 | ||||
| int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) | ||||
| { | ||||
| 	struct b43_phy *phy = &(dev->phy); | ||||
| 	u16 channelcookie, savedcookie; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (new_channel == B43_DEFAULT_CHANNEL) | ||||
| 		new_channel = phy->ops->get_default_chan(dev); | ||||
| 
 | ||||
| 	/* First we set the channel radio code to prevent the
 | ||||
| 	 * firmware from sending ghost packets. | ||||
| 	 */ | ||||
| 	channelcookie = new_channel; | ||||
| 	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||||
| 		channelcookie |= 0x100; | ||||
| 	//FIXME set 40Mhz flag if required
 | ||||
| 	savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); | ||||
| 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); | ||||
| 
 | ||||
| 	/* Now try to switch the PHY hardware channel. */ | ||||
| 	err = phy->ops->switch_channel(dev, new_channel); | ||||
| 	if (err) | ||||
| 		goto err_restore_cookie; | ||||
| 
 | ||||
| 	dev->phy.channel = new_channel; | ||||
| 	/* Wait for the radio to tune to the channel and stabilize. */ | ||||
| 	msleep(8); | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| err_restore_cookie: | ||||
| 	b43_shm_write16(dev, B43_SHM_SHARED, | ||||
| 			B43_SHM_SH_CHAN, savedcookie); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 
 | ||||
| 	if (state == RFKILL_STATE_HARD_BLOCKED) { | ||||
| 		/* We cannot hardware-block the device */ | ||||
| 		state = RFKILL_STATE_SOFT_BLOCKED; | ||||
| 	} | ||||
| 
 | ||||
| 	phy->ops->software_rfkill(dev, state); | ||||
| 	phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); | ||||
| } | ||||
							
								
								
									
										312
									
								
								drivers/net/wireless/b43/phy_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								drivers/net/wireless/b43/phy_common.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,312 @@ | ||||
| #ifndef LINUX_B43_PHY_COMMON_H_ | ||||
| #define LINUX_B43_PHY_COMMON_H_ | ||||
| 
 | ||||
| #include <linux/rfkill.h> | ||||
| 
 | ||||
| struct b43_wldev; | ||||
| 
 | ||||
| 
 | ||||
| /* PHY register routing bits */ | ||||
| #define B43_PHYROUTE			0x0C00 /* PHY register routing bits mask */ | ||||
| #define  B43_PHYROUTE_BASE		0x0000 /* Base registers */ | ||||
| #define  B43_PHYROUTE_OFDM_GPHY		0x0400 /* OFDM register routing for G-PHYs */ | ||||
| #define  B43_PHYROUTE_EXT_GPHY		0x0800 /* Extended G-PHY registers */ | ||||
| #define  B43_PHYROUTE_N_BMODE		0x0C00 /* N-PHY BMODE registers */ | ||||
| 
 | ||||
| /* CCK (B-PHY) registers. */ | ||||
| #define B43_PHY_CCK(reg)		((reg) | B43_PHYROUTE_BASE) | ||||
| /* N-PHY registers. */ | ||||
| #define B43_PHY_N(reg)			((reg) | B43_PHYROUTE_BASE) | ||||
| /* N-PHY BMODE registers. */ | ||||
| #define B43_PHY_N_BMODE(reg)		((reg) | B43_PHYROUTE_N_BMODE) | ||||
| /* OFDM (A-PHY) registers. */ | ||||
| #define B43_PHY_OFDM(reg)		((reg) | B43_PHYROUTE_OFDM_GPHY) | ||||
| /* Extended G-PHY registers. */ | ||||
| #define B43_PHY_EXTG(reg)		((reg) | B43_PHYROUTE_EXT_GPHY) | ||||
| 
 | ||||
| 
 | ||||
| /* Masks for the PHY versioning registers. */ | ||||
| #define B43_PHYVER_ANALOG		0xF000 | ||||
| #define B43_PHYVER_ANALOG_SHIFT		12 | ||||
| #define B43_PHYVER_TYPE			0x0F00 | ||||
| #define B43_PHYVER_TYPE_SHIFT		8 | ||||
| #define B43_PHYVER_VERSION		0x00FF | ||||
| 
 | ||||
| /**
 | ||||
|  * enum b43_interference_mitigation - Interference Mitigation mode | ||||
|  * | ||||
|  * @B43_INTERFMODE_NONE:	Disabled | ||||
|  * @B43_INTERFMODE_NONWLAN:	Non-WLAN Interference Mitigation | ||||
|  * @B43_INTERFMODE_MANUALWLAN:	WLAN Interference Mitigation | ||||
|  * @B43_INTERFMODE_AUTOWLAN:	Automatic WLAN Interference Mitigation | ||||
|  */ | ||||
| enum b43_interference_mitigation { | ||||
| 	B43_INTERFMODE_NONE, | ||||
| 	B43_INTERFMODE_NONWLAN, | ||||
| 	B43_INTERFMODE_MANUALWLAN, | ||||
| 	B43_INTERFMODE_AUTOWLAN, | ||||
| }; | ||||
| 
 | ||||
| /* Antenna identifiers */ | ||||
| enum { | ||||
| 	B43_ANTENNA0,		/* Antenna 0 */ | ||||
| 	B43_ANTENNA1,		/* Antenna 0 */ | ||||
| 	B43_ANTENNA_AUTO1,	/* Automatic, starting with antenna 1 */ | ||||
| 	B43_ANTENNA_AUTO0,	/* Automatic, starting with antenna 0 */ | ||||
| 	B43_ANTENNA2, | ||||
| 	B43_ANTENNA3 = 8, | ||||
| 
 | ||||
| 	B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, | ||||
| 	B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct b43_phy_operations - Function pointers for PHY ops. | ||||
|  * | ||||
|  * @prepare:		Prepare the PHY. This is called before @init. | ||||
|  * 			Can be NULL, if not required. | ||||
|  * @init:		Initialize the PHY. | ||||
|  * 			Must not be NULL. | ||||
|  * @exit:		Shutdown the PHY and free all data structures. | ||||
|  * 			Can be NULL, if not required. | ||||
|  * | ||||
|  * @phy_read:		Read from a PHY register. | ||||
|  * 			Must not be NULL. | ||||
|  * @phy_write:		Write to a PHY register. | ||||
|  * 			Must not be NULL. | ||||
|  * @radio_read:		Read from a Radio register. | ||||
|  * 			Must not be NULL. | ||||
|  * @radio_write:	Write to a Radio register. | ||||
|  * 			Must not be NULL. | ||||
|  * | ||||
|  * @supports_hwpctl:	Returns a boolean whether Hardware Power Control | ||||
|  * 			is supported or not. | ||||
|  * 			If NULL, hwpctl is assumed to be never supported. | ||||
|  * @software_rfkill:	Turn the radio ON or OFF. | ||||
|  * 			Possible state values are | ||||
|  * 			RFKILL_STATE_SOFT_BLOCKED or | ||||
|  * 			RFKILL_STATE_UNBLOCKED | ||||
|  * 			Must not be NULL. | ||||
|  * @switch_channel:	Switch the radio to another channel. | ||||
|  * 			Must not be NULL. | ||||
|  * @get_default_chan:	Just returns the default channel number. | ||||
|  * 			Must not be NULL. | ||||
|  * @set_rx_antenna:	Set the antenna used for RX. | ||||
|  * 			Can be NULL, if not supported. | ||||
|  * @interf_mitigation:	Switch the Interference Mitigation mode. | ||||
|  * 			Can be NULL, if not supported. | ||||
|  * | ||||
|  * @xmitpower:		FIXME REMOVEME | ||||
|  * 			Must not be NULL. | ||||
|  * | ||||
|  * @pwork_15sec:	Periodic work. Called every 15 seconds. | ||||
|  * 			Can be NULL, if not required. | ||||
|  * @pwork_60sec:	Periodic work. Called every 60 seconds. | ||||
|  * 			Can be NULL, if not required. | ||||
|  */ | ||||
| struct b43_phy_operations { | ||||
| 	/* Initialisation */ | ||||
| 	int (*allocate)(struct b43_wldev *dev); | ||||
| 	int (*prepare)(struct b43_wldev *dev); | ||||
| 	int (*init)(struct b43_wldev *dev); | ||||
| 	void (*exit)(struct b43_wldev *dev); | ||||
| 
 | ||||
| 	/* Register access */ | ||||
| 	u16 (*phy_read)(struct b43_wldev *dev, u16 reg); | ||||
| 	void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value); | ||||
| 	u16 (*radio_read)(struct b43_wldev *dev, u16 reg); | ||||
| 	void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value); | ||||
| 
 | ||||
| 	/* Radio */ | ||||
| 	bool (*supports_hwpctl)(struct b43_wldev *dev); | ||||
| 	void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state); | ||||
| 	int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel); | ||||
| 	unsigned int (*get_default_chan)(struct b43_wldev *dev); | ||||
| 	void (*set_rx_antenna)(struct b43_wldev *dev, int antenna); | ||||
| 	int (*interf_mitigation)(struct b43_wldev *dev, | ||||
| 				 enum b43_interference_mitigation new_mode); | ||||
| 
 | ||||
| 	/* Transmission power adjustment */ | ||||
| 	void (*xmitpower)(struct b43_wldev *dev); | ||||
| 
 | ||||
| 	/* Misc */ | ||||
| 	void (*pwork_15sec)(struct b43_wldev *dev); | ||||
| 	void (*pwork_60sec)(struct b43_wldev *dev); | ||||
| }; | ||||
| 
 | ||||
| struct b43_phy_a; | ||||
| struct b43_phy_g; | ||||
| struct b43_phy_n; | ||||
| 
 | ||||
| struct b43_phy { | ||||
| 	/* Hardware operation callbacks. */ | ||||
| 	const struct b43_phy_operations *ops; | ||||
| 
 | ||||
| 	/* Most hardware context information is stored in the standard-
 | ||||
| 	 * specific data structures pointed to by the pointers below. | ||||
| 	 * Only one of them is valid (the currently enabled PHY). */ | ||||
| #ifdef CONFIG_B43_DEBUG | ||||
| 	/* No union for debug build to force NULL derefs in buggy code. */ | ||||
| 	struct { | ||||
| #else | ||||
| 	union { | ||||
| #endif | ||||
| 		/* A-PHY specific information */ | ||||
| 		struct b43_phy_a *a; | ||||
| 		/* G-PHY specific information */ | ||||
| 		struct b43_phy_g *g; | ||||
| 		/* N-PHY specific information */ | ||||
| 		struct b43_phy_n *n; | ||||
| 	}; | ||||
| 
 | ||||
| 	/* Band support flags. */ | ||||
| 	bool supports_2ghz; | ||||
| 	bool supports_5ghz; | ||||
| 
 | ||||
| 	/* GMODE bit enabled? */ | ||||
| 	bool gmode; | ||||
| 
 | ||||
| 	/* Analog Type */ | ||||
| 	u8 analog; | ||||
| 	/* B43_PHYTYPE_ */ | ||||
| 	u8 type; | ||||
| 	/* PHY revision number. */ | ||||
| 	u8 rev; | ||||
| 
 | ||||
| 	/* Radio versioning */ | ||||
| 	u16 radio_manuf;	/* Radio manufacturer */ | ||||
| 	u16 radio_ver;		/* Radio version */ | ||||
| 	u8 radio_rev;		/* Radio revision */ | ||||
| 
 | ||||
| 	/* Software state of the radio */ | ||||
| 	bool radio_on; | ||||
| 
 | ||||
| 	/* Desired TX power level (in dBm).
 | ||||
| 	 * This is set by the user and adjusted in b43_phy_xmitpower(). */ | ||||
| 	u8 power_level; | ||||
| 
 | ||||
| 	/* Hardware Power Control enabled? */ | ||||
| 	bool hardware_power_control; | ||||
| 
 | ||||
| 	/* current channel */ | ||||
| 	unsigned int channel; | ||||
| 
 | ||||
| 	/* PHY TX errors counter. */ | ||||
| 	atomic_t txerr_cnt; | ||||
| 
 | ||||
| #ifdef CONFIG_B43_DEBUG | ||||
| 	/* PHY registers locked by b43_phy_lock()? */ | ||||
| 	bool phy_locked; | ||||
| #endif /* B43_DEBUG */ | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_operations_setup - Initialize the PHY operations datastructure | ||||
|  * based on the current PHY type. | ||||
|  */ | ||||
| int b43_phy_operations_setup(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_init - Initialise the PHY | ||||
|  */ | ||||
| int b43_phy_init(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_exit - Cleanup PHY | ||||
|  */ | ||||
| void b43_phy_exit(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_has_hardware_pctl - Hardware Power Control supported? | ||||
|  * Returns a boolean, whether hardware power control is supported. | ||||
|  */ | ||||
| bool b43_has_hardware_pctl(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_read - 16bit PHY register read access | ||||
|  */ | ||||
| u16 b43_phy_read(struct b43_wldev *dev, u16 reg); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_write - 16bit PHY register write access | ||||
|  */ | ||||
| void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_mask - Mask a PHY register with a mask | ||||
|  */ | ||||
| void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_set - OR a PHY register with a bitmap | ||||
|  */ | ||||
| void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap | ||||
|  */ | ||||
| void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_read - 16bit Radio register read access | ||||
|  */ | ||||
| u16 b43_radio_read(struct b43_wldev *dev, u16 reg); | ||||
| #define b43_radio_read16	b43_radio_read /* DEPRECATED */ | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_write - 16bit Radio register write access | ||||
|  */ | ||||
| void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value); | ||||
| #define b43_radio_write16	b43_radio_write /* DEPRECATED */ | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_mask - Mask a 16bit radio register with a mask | ||||
|  */ | ||||
| void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_set - OR a 16bit radio register with a bitmap | ||||
|  */ | ||||
| void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_maskset - Mask and OR a radio register with a mask and bitmap | ||||
|  */ | ||||
| void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_lock - Lock firmware radio register access | ||||
|  */ | ||||
| void b43_radio_lock(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_radio_unlock - Unlock firmware radio register access | ||||
|  */ | ||||
| void b43_radio_unlock(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_lock - Lock firmware PHY register access | ||||
|  */ | ||||
| void b43_phy_lock(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_phy_unlock - Unlock firmware PHY register access | ||||
|  */ | ||||
| void b43_phy_unlock(struct b43_wldev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_switch_channel - Switch to another channel | ||||
|  */ | ||||
| int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel); | ||||
| /**
 | ||||
|  * B43_DEFAULT_CHANNEL - Switch to the default channel. | ||||
|  */ | ||||
| #define B43_DEFAULT_CHANNEL	UINT_MAX | ||||
| 
 | ||||
| /**
 | ||||
|  * b43_software_rfkill - Turn the radio ON or OFF in software. | ||||
|  */ | ||||
| void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state); | ||||
| 
 | ||||
| #endif /* LINUX_B43_PHY_COMMON_H_ */ | ||||
							
								
								
									
										3229
									
								
								drivers/net/wireless/b43/phy_g.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3229
									
								
								drivers/net/wireless/b43/phy_g.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										201
									
								
								drivers/net/wireless/b43/phy_g.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								drivers/net/wireless/b43/phy_g.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,201 @@ | ||||
| #ifndef LINUX_B43_PHY_G_H_ | ||||
| #define LINUX_B43_PHY_G_H_ | ||||
| 
 | ||||
| /* OFDM PHY registers are defined in the A-PHY header. */ | ||||
| #include "phy_a.h" | ||||
| 
 | ||||
| /* CCK (B) PHY Registers */ | ||||
| #define B43_PHY_VERSION_CCK		B43_PHY_CCK(0x00)	/* Versioning register for B-PHY */ | ||||
| #define B43_PHY_CCKBBANDCFG		B43_PHY_CCK(0x01)	/* Contains antenna 0/1 control bit */ | ||||
| #define B43_PHY_PGACTL			B43_PHY_CCK(0x15)	/* PGA control */ | ||||
| #define  B43_PHY_PGACTL_LPF		0x1000	/* Low pass filter (?) */ | ||||
| #define  B43_PHY_PGACTL_LOWBANDW	0x0040	/* Low bandwidth flag */ | ||||
| #define  B43_PHY_PGACTL_UNKNOWN		0xEFA0 | ||||
| #define B43_PHY_FBCTL1			B43_PHY_CCK(0x18)	/* Frequency bandwidth control 1 */ | ||||
| #define B43_PHY_ITSSI			B43_PHY_CCK(0x29)	/* Idle TSSI */ | ||||
| #define B43_PHY_LO_LEAKAGE		B43_PHY_CCK(0x2D)	/* Measured LO leakage */ | ||||
| #define B43_PHY_ENERGY			B43_PHY_CCK(0x33)	/* Energy */ | ||||
| #define B43_PHY_SYNCCTL			B43_PHY_CCK(0x35) | ||||
| #define B43_PHY_FBCTL2			B43_PHY_CCK(0x38)	/* Frequency bandwidth control 2 */ | ||||
| #define B43_PHY_DACCTL			B43_PHY_CCK(0x60)	/* DAC control */ | ||||
| #define B43_PHY_RCCALOVER		B43_PHY_CCK(0x78)	/* RC calibration override */ | ||||
| 
 | ||||
| /* Extended G-PHY Registers */ | ||||
| #define B43_PHY_CLASSCTL		B43_PHY_EXTG(0x02)	/* Classify control */ | ||||
| #define B43_PHY_GTABCTL			B43_PHY_EXTG(0x03)	/* G-PHY table control (see below) */ | ||||
| #define  B43_PHY_GTABOFF		0x03FF	/* G-PHY table offset (see below) */ | ||||
| #define  B43_PHY_GTABNR			0xFC00	/* G-PHY table number (see below) */ | ||||
| #define  B43_PHY_GTABNR_SHIFT		10 | ||||
| #define B43_PHY_GTABDATA		B43_PHY_EXTG(0x04)	/* G-PHY table data */ | ||||
| #define B43_PHY_LO_MASK			B43_PHY_EXTG(0x0F)	/* Local Oscillator control mask */ | ||||
| #define B43_PHY_LO_CTL			B43_PHY_EXTG(0x10)	/* Local Oscillator control */ | ||||
| #define B43_PHY_RFOVER			B43_PHY_EXTG(0x11)	/* RF override */ | ||||
| #define B43_PHY_RFOVERVAL		B43_PHY_EXTG(0x12)	/* RF override value */ | ||||
| #define  B43_PHY_RFOVERVAL_EXTLNA	0x8000 | ||||
| #define  B43_PHY_RFOVERVAL_LNA		0x7000 | ||||
| #define  B43_PHY_RFOVERVAL_LNA_SHIFT	12 | ||||
| #define  B43_PHY_RFOVERVAL_PGA		0x0F00 | ||||
| #define  B43_PHY_RFOVERVAL_PGA_SHIFT	8 | ||||
| #define  B43_PHY_RFOVERVAL_UNK		0x0010	/* Unknown, always set. */ | ||||
| #define  B43_PHY_RFOVERVAL_TRSWRX	0x00E0 | ||||
| #define  B43_PHY_RFOVERVAL_BW		0x0003	/* Bandwidth flags */ | ||||
| #define   B43_PHY_RFOVERVAL_BW_LPF	0x0001	/* Low Pass Filter */ | ||||
| #define   B43_PHY_RFOVERVAL_BW_LBW	0x0002	/* Low Bandwidth (when set), high when unset */ | ||||
| #define B43_PHY_ANALOGOVER		B43_PHY_EXTG(0x14)	/* Analog override */ | ||||
| #define B43_PHY_ANALOGOVERVAL		B43_PHY_EXTG(0x15)	/* Analog override value */ | ||||
| 
 | ||||
| 
 | ||||
| /*** G-PHY table numbers */ | ||||
| #define B43_GTAB(number, offset)	(((number) << B43_PHY_GTABNR_SHIFT) | (offset)) | ||||
| #define B43_GTAB_NRSSI			B43_GTAB(0x00, 0) | ||||
| #define B43_GTAB_TRFEMW			B43_GTAB(0x0C, 0x120) | ||||
| #define B43_GTAB_ORIGTR			B43_GTAB(0x2E, 0x298) | ||||
| 
 | ||||
| u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); | ||||
| void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); | ||||
| 
 | ||||
| 
 | ||||
| /* Returns the boolean whether "TX Magnification" is enabled. */ | ||||
| #define has_tx_magnification(phy) \ | ||||
| 	(((phy)->rev >= 2) &&			\ | ||||
| 	 ((phy)->radio_ver == 0x2050) &&	\ | ||||
| 	 ((phy)->radio_rev == 8)) | ||||
| /* Card uses the loopback gain stuff */ | ||||
| #define has_loopback_gain(phy) \ | ||||
| 	(((phy)->rev > 1) || ((phy)->gmode)) | ||||
| 
 | ||||
| /* Radio Attenuation (RF Attenuation) */ | ||||
| struct b43_rfatt { | ||||
| 	u8 att;			/* Attenuation value */ | ||||
| 	bool with_padmix;	/* Flag, PAD Mixer enabled. */ | ||||
| }; | ||||
| struct b43_rfatt_list { | ||||
| 	/* Attenuation values list */ | ||||
| 	const struct b43_rfatt *list; | ||||
| 	u8 len; | ||||
| 	/* Minimum/Maximum attenuation values */ | ||||
| 	u8 min_val; | ||||
| 	u8 max_val; | ||||
| }; | ||||
| 
 | ||||
| /* Returns true, if the values are the same. */ | ||||
| static inline bool b43_compare_rfatt(const struct b43_rfatt *a, | ||||
| 				     const struct b43_rfatt *b) | ||||
| { | ||||
| 	return ((a->att == b->att) && | ||||
| 		(a->with_padmix == b->with_padmix)); | ||||
| } | ||||
| 
 | ||||
| /* Baseband Attenuation */ | ||||
| struct b43_bbatt { | ||||
| 	u8 att;			/* Attenuation value */ | ||||
| }; | ||||
| struct b43_bbatt_list { | ||||
| 	/* Attenuation values list */ | ||||
| 	const struct b43_bbatt *list; | ||||
| 	u8 len; | ||||
| 	/* Minimum/Maximum attenuation values */ | ||||
| 	u8 min_val; | ||||
| 	u8 max_val; | ||||
| }; | ||||
| 
 | ||||
| /* Returns true, if the values are the same. */ | ||||
| static inline bool b43_compare_bbatt(const struct b43_bbatt *a, | ||||
| 				     const struct b43_bbatt *b) | ||||
| { | ||||
| 	return (a->att == b->att); | ||||
| } | ||||
| 
 | ||||
| /* tx_control bits. */ | ||||
| #define B43_TXCTL_PA3DB		0x40	/* PA Gain 3dB */ | ||||
| #define B43_TXCTL_PA2DB		0x20	/* PA Gain 2dB */ | ||||
| #define B43_TXCTL_TXMIX		0x10	/* TX Mixer Gain */ | ||||
| 
 | ||||
| struct b43_txpower_lo_control; | ||||
| 
 | ||||
| struct b43_phy_g { | ||||
| 	bool initialised; | ||||
| 	bool dyn_tssi_tbl;	/* tssi2dbm is kmalloc()ed. */ | ||||
| 
 | ||||
| 	/* ACI (adjacent channel interference) flags. */ | ||||
| 	bool aci_enable; | ||||
| 	bool aci_wlan_automatic; | ||||
| 	bool aci_hw_rssi; | ||||
| 
 | ||||
| 	/* Radio switched on/off */ | ||||
| 	bool radio_on; | ||||
| 	struct { | ||||
| 		/* Values saved when turning the radio off.
 | ||||
| 		 * They are needed when turning it on again. */ | ||||
| 		bool valid; | ||||
| 		u16 rfover; | ||||
| 		u16 rfoverval; | ||||
| 	} radio_off_context; | ||||
| 
 | ||||
| 	u16 minlowsig[2]; | ||||
| 	u16 minlowsigpos[2]; | ||||
| 
 | ||||
| 	/* TSSI to dBm table in use */ | ||||
| 	const s8 *tssi2dbm; | ||||
| 	/* Target idle TSSI */ | ||||
| 	int tgt_idle_tssi; | ||||
| 	/* Current idle TSSI */ | ||||
| 	int cur_idle_tssi; | ||||
| 
 | ||||
| 	/* LocalOscillator control values. */ | ||||
| 	struct b43_txpower_lo_control *lo_control; | ||||
| 	/* Values from b43_calc_loopback_gain() */ | ||||
| 	s16 max_lb_gain;	/* Maximum Loopback gain in hdB */ | ||||
| 	s16 trsw_rx_gain;	/* TRSW RX gain in hdB */ | ||||
| 	s16 lna_lod_gain;	/* LNA lod */ | ||||
| 	s16 lna_gain;		/* LNA */ | ||||
| 	s16 pga_gain;		/* PGA */ | ||||
| 
 | ||||
| 	/* Current TX power level attenuation control values */ | ||||
| 	struct b43_bbatt bbatt; | ||||
| 	struct b43_rfatt rfatt; | ||||
| 	u8 tx_control;		/* B43_TXCTL_XXX */ | ||||
| 
 | ||||
| 	/* Current Interference Mitigation mode */ | ||||
| 	int interfmode; | ||||
| 	/* Stack of saved values from the Interference Mitigation code.
 | ||||
| 	 * Each value in the stack is layed out as follows: | ||||
| 	 * bit 0-11:  offset | ||||
| 	 * bit 12-15: register ID | ||||
| 	 * bit 16-32: value | ||||
| 	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT | ||||
| 	 */ | ||||
| #define B43_INTERFSTACK_SIZE	26 | ||||
| 	u32 interfstack[B43_INTERFSTACK_SIZE];	//FIXME: use a data structure
 | ||||
| 
 | ||||
| 	/* Saved values from the NRSSI Slope calculation */ | ||||
| 	s16 nrssi[2]; | ||||
| 	s32 nrssislope; | ||||
| 	/* In memory nrssi lookup table. */ | ||||
| 	s8 nrssi_lt[64]; | ||||
| 
 | ||||
| 	u16 lofcal; | ||||
| 
 | ||||
| 	u16 initval;		//FIXME rename?
 | ||||
| 
 | ||||
| 	/* The device does address auto increment for the OFDM tables.
 | ||||
| 	 * We cache the previously used address here and omit the address | ||||
| 	 * write on the next table access, if possible. */ | ||||
| 	u16 ofdmtab_addr; /* The address currently set in hardware. */ | ||||
| 	enum { /* The last data flow direction. */ | ||||
| 		B43_OFDMTAB_DIRECTION_UNKNOWN = 0, | ||||
| 		B43_OFDMTAB_DIRECTION_READ, | ||||
| 		B43_OFDMTAB_DIRECTION_WRITE, | ||||
| 	} ofdmtab_addr_direction; | ||||
| }; | ||||
| 
 | ||||
| void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, | ||||
| 				       u16 baseband_attenuation); | ||||
| void b43_gphy_channel_switch(struct b43_wldev *dev, | ||||
| 			     unsigned int channel, | ||||
| 			     bool synthetic_pu_workaround); | ||||
| 
 | ||||
| struct b43_phy_operations; | ||||
| extern const struct b43_phy_operations b43_phyops_g; | ||||
| 
 | ||||
| #endif /* LINUX_B43_PHY_G_H_ */ | ||||
| @ -24,6 +24,7 @@ | ||||
| 
 | ||||
| #include "rfkill.h" | ||||
| #include "b43.h" | ||||
| #include "phy_common.h" | ||||
| 
 | ||||
| #include <linux/kmod.h> | ||||
| 
 | ||||
| @ -114,11 +115,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | ||||
| 			goto out_unlock; | ||||
| 		} | ||||
| 		if (!dev->phy.radio_on) | ||||
| 			b43_radio_turn_on(dev); | ||||
| 			b43_software_rfkill(dev, state); | ||||
| 		break; | ||||
| 	case RFKILL_STATE_SOFT_BLOCKED: | ||||
| 		if (dev->phy.radio_on) | ||||
| 			b43_radio_turn_off(dev, 0); | ||||
| 			b43_software_rfkill(dev, state); | ||||
| 		break; | ||||
| 	default: | ||||
| 		b43warn(wl, "Received unexpected rfkill state %d.\n", state); | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| #include "b43.h" | ||||
| #include "sysfs.h" | ||||
| #include "main.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| 
 | ||||
| #define GENERIC_FILESIZE	64 | ||||
| 
 | ||||
| @ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev, | ||||
| 
 | ||||
| 	mutex_lock(&wldev->wl->mutex); | ||||
| 
 | ||||
| 	switch (wldev->phy.interfmode) { | ||||
| 	if (wldev->phy.type != B43_PHYTYPE_G) { | ||||
| 		mutex_unlock(&wldev->wl->mutex); | ||||
| 		return -ENOSYS; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (wldev->phy.g->interfmode) { | ||||
| 	case B43_INTERFMODE_NONE: | ||||
| 		count = | ||||
| 		    snprintf(buf, PAGE_SIZE, | ||||
| @ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, | ||||
| 	mutex_lock(&wldev->wl->mutex); | ||||
| 	spin_lock_irqsave(&wldev->wl->irq_lock, flags); | ||||
| 
 | ||||
| 	err = b43_radio_set_interference_mitigation(wldev, mode); | ||||
| 	if (err) { | ||||
| 		b43err(wldev->wl, "Interference Mitigation not " | ||||
| 		       "supported by device\n"); | ||||
| 	} | ||||
| 	if (wldev->phy.ops->interf_mitigation) { | ||||
| 		err = wldev->phy.ops->interf_mitigation(wldev, mode); | ||||
| 		if (err) { | ||||
| 			b43err(wldev->wl, "Interference Mitigation not " | ||||
| 			       "supported by device\n"); | ||||
| 		} | ||||
| 	} else | ||||
| 		err = -ENOSYS; | ||||
| 
 | ||||
| 	mmiowb(); | ||||
| 	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); | ||||
| 	mutex_unlock(&wldev->wl->mutex); | ||||
|  | ||||
| @ -27,7 +27,8 @@ | ||||
| 
 | ||||
| #include "b43.h" | ||||
| #include "tables.h" | ||||
| #include "phy.h" | ||||
| #include "phy_g.h" | ||||
| 
 | ||||
| 
 | ||||
| const u32 b43_tab_rotor[] = { | ||||
| 	0xFEB93FFD, 0xFEC63FFD,	/* 0 */ | ||||
| @ -377,17 +378,17 @@ static inline void assert_sizes(void) | ||||
| 
 | ||||
| u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = dev->phy.g; | ||||
| 	u16 addr; | ||||
| 
 | ||||
| 	addr = table + offset; | ||||
| 	if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | ||||
| 	    (addr - 1 != phy->ofdmtab_addr)) { | ||||
| 	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | ||||
| 	    (addr - 1 != gphy->ofdmtab_addr)) { | ||||
| 		/* The hardware has a different address in memory. Update it. */ | ||||
| 		b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | ||||
| 		phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | ||||
| 		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | ||||
| 	} | ||||
| 	phy->ofdmtab_addr = addr; | ||||
| 	gphy->ofdmtab_addr = addr; | ||||
| 
 | ||||
| 	return b43_phy_read(dev, B43_PHY_OTABLEI); | ||||
| 
 | ||||
| @ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) | ||||
| void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u16 value) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = dev->phy.g; | ||||
| 	u16 addr; | ||||
| 
 | ||||
| 	addr = table + offset; | ||||
| 	if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | ||||
| 	    (addr - 1 != phy->ofdmtab_addr)) { | ||||
| 	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | ||||
| 	    (addr - 1 != gphy->ofdmtab_addr)) { | ||||
| 		/* The hardware has a different address in memory. Update it. */ | ||||
| 		b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | ||||
| 		phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | ||||
| 		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | ||||
| 	} | ||||
| 	phy->ofdmtab_addr = addr; | ||||
| 	gphy->ofdmtab_addr = addr; | ||||
| 	b43_phy_write(dev, B43_PHY_OTABLEI, value); | ||||
| } | ||||
| 
 | ||||
| u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = dev->phy.g; | ||||
| 	u32 ret; | ||||
| 	u16 addr; | ||||
| 
 | ||||
| 	addr = table + offset; | ||||
| 	if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | ||||
| 	    (addr - 1 != phy->ofdmtab_addr)) { | ||||
| 	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | ||||
| 	    (addr - 1 != gphy->ofdmtab_addr)) { | ||||
| 		/* The hardware has a different address in memory. Update it. */ | ||||
| 		b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | ||||
| 		phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | ||||
| 		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | ||||
| 	} | ||||
| 	phy->ofdmtab_addr = addr; | ||||
| 	gphy->ofdmtab_addr = addr; | ||||
| 	ret = b43_phy_read(dev, B43_PHY_OTABLEQ); | ||||
| 	ret <<= 16; | ||||
| 	ret |= b43_phy_read(dev, B43_PHY_OTABLEI); | ||||
| @ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) | ||||
| void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | ||||
| 			 u16 offset, u32 value) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = dev->phy.g; | ||||
| 	u16 addr; | ||||
| 
 | ||||
| 	addr = table + offset; | ||||
| 	if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | ||||
| 	    (addr - 1 != phy->ofdmtab_addr)) { | ||||
| 	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | ||||
| 	    (addr - 1 != gphy->ofdmtab_addr)) { | ||||
| 		/* The hardware has a different address in memory. Update it. */ | ||||
| 		b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | ||||
| 		phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | ||||
| 		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | ||||
| 	} | ||||
| 	phy->ofdmtab_addr = addr; | ||||
| 	gphy->ofdmtab_addr = addr; | ||||
| 
 | ||||
| 	b43_phy_write(dev, B43_PHY_OTABLEI, value); | ||||
| 	b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16)); | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
| 
 | ||||
| #include "b43.h" | ||||
| #include "tables_nphy.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| #include "nphy.h" | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -27,7 +27,7 @@ | ||||
| #include "b43.h" | ||||
| #include "main.h" | ||||
| #include "tables.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| #include "wa.h" | ||||
| 
 | ||||
| static void b43_wa_papd(struct b43_wldev *dev) | ||||
|  | ||||
| @ -28,7 +28,7 @@ | ||||
| */ | ||||
| 
 | ||||
| #include "xmit.h" | ||||
| #include "phy.h" | ||||
| #include "phy_common.h" | ||||
| #include "dma.h" | ||||
| #include "pio.h" | ||||
| 
 | ||||
| @ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, | ||||
| 			       int adjust_2053, int adjust_2050) | ||||
| { | ||||
| 	struct b43_phy *phy = &dev->phy; | ||||
| 	struct b43_phy_g *gphy = phy->g; | ||||
| 	s32 tmp; | ||||
| 
 | ||||
| 	switch (phy->radio_ver) { | ||||
| @ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, | ||||
| 			    boardflags_lo & B43_BFL_RSSI) { | ||||
| 				if (in_rssi > 63) | ||||
| 					in_rssi = 63; | ||||
| 				tmp = phy->nrssi_lt[in_rssi]; | ||||
| 				B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||||
| 				tmp = gphy->nrssi_lt[in_rssi]; | ||||
| 				tmp = 31 - tmp; | ||||
| 				tmp *= -131; | ||||
| 				tmp /= 128; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user