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

📄 bcm43xx_radio.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		else			mode = BCM43xx_RADIO_INTERFMODE_NONE;		break;	case BCM43xx_RADIO_INTERFMODE_NONE:	case BCM43xx_RADIO_INTERFMODE_NONWLAN:	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		break;	default:		return -EINVAL;	}	currentmode = radio->interfmode;	if (currentmode == mode)		return 0;	if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)		bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);	if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {		radio->aci_enable = 0;		radio->aci_hw_rssi = 0;	} else		bcm43xx_radio_interference_mitigation_enable(bcm, mode);	radio->interfmode = mode;	return 0;}u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm){	u16 reg, index, ret;	reg = bcm43xx_radio_read16(bcm, 0x0060);	index = (reg & 0x001E) >> 1;	ret = rcc_table[index] << 1;	ret |= (reg & 0x0001);	ret |= 0x0020;	return ret;}#define LPD(L, P, D)    (((L) << 2) | ((P) << 1) | ((D) << 0))static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 loop_or = 0;	u16 adj_loopback_gain = phy->loopback_gain[0];	u8 loop;	u16 extern_lna_control;	if (!phy->connected)		return 0;	if (!has_loopback_gain(phy)) {		if (phy->rev < 7 || !(bcm->sprom.boardflags		    & BCM43xx_BFL_EXTLNA)) {			switch (lpd) {			case LPD(0, 1, 1):				return 0x0FB2;			case LPD(0, 0, 1):				return 0x00B2;			case LPD(1, 0, 1):				return 0x30B2;			case LPD(1, 0, 0):				return 0x30B3;			default:				assert(0);			}		} else {			switch (lpd) {			case LPD(0, 1, 1):				return 0x8FB2;			case LPD(0, 0, 1):				return 0x80B2;			case LPD(1, 0, 1):				return 0x20B2;			case LPD(1, 0, 0):				return 0x20B3;			default:				assert(0);			}		}	} else {		if (radio->revision == 8)			adj_loopback_gain += 0x003E;		else			adj_loopback_gain += 0x0026;		if (adj_loopback_gain >= 0x46) {			adj_loopback_gain -= 0x46;			extern_lna_control = 0x3000;		} else if (adj_loopback_gain >= 0x3A) {			adj_loopback_gain -= 0x3A;			extern_lna_control = 0x2000;		} else if (adj_loopback_gain >= 0x2E) {			adj_loopback_gain -= 0x2E;			extern_lna_control = 0x1000;		} else {			adj_loopback_gain -= 0x10;			extern_lna_control = 0x0000;		}		for (loop = 0; loop < 16; loop++) {			u16 tmp = adj_loopback_gain - 6 * loop;			if (tmp < 6)				break;		}		loop_or = (loop << 8) | extern_lna_control;		if (phy->rev >= 7 && bcm->sprom.boardflags		    & BCM43xx_BFL_EXTLNA) {			if (extern_lna_control)				loop_or |= 0x8000;			switch (lpd) {			case LPD(0, 1, 1):				return 0x8F92;			case LPD(0, 0, 1):				return (0x8092 | loop_or);			case LPD(1, 0, 1):				return (0x2092 | loop_or);			case LPD(1, 0, 0):				return (0x2093 | loop_or);			default:				assert(0);			}		} else {			switch (lpd) {			case LPD(0, 1, 1):				return 0x0F92;			case LPD(0, 0, 1):			case LPD(1, 0, 1):				return (0x0092 | loop_or);			case LPD(1, 0, 0):				return (0x0093 | loop_or);			default:				assert(0);			}		}	}	return 0;}u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 backup[21] = { 0 };	u16 ret;	u16 i, j;	u32 tmp1 = 0, tmp2 = 0;	backup[0] = bcm43xx_radio_read16(bcm, 0x0043);	backup[14] = bcm43xx_radio_read16(bcm, 0x0051);	backup[15] = bcm43xx_radio_read16(bcm, 0x0052);	backup[1] = bcm43xx_phy_read(bcm, 0x0015);	backup[16] = bcm43xx_phy_read(bcm, 0x005A);	backup[17] = bcm43xx_phy_read(bcm, 0x0059);	backup[18] = bcm43xx_phy_read(bcm, 0x0058);	if (phy->type == BCM43xx_PHYTYPE_B) {		backup[2] = bcm43xx_phy_read(bcm, 0x0030);		backup[3] = bcm43xx_read16(bcm, 0x03EC);		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);	} else {		if (phy->connected) {			backup[4] = bcm43xx_phy_read(bcm, 0x0811);			backup[5] = bcm43xx_phy_read(bcm, 0x0812);			backup[6] = bcm43xx_phy_read(bcm, 0x0814);			backup[7] = bcm43xx_phy_read(bcm, 0x0815);			backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);			backup[9] = bcm43xx_phy_read(bcm, 0x0802);			bcm43xx_phy_write(bcm, 0x0814,			                  (bcm43xx_phy_read(bcm, 0x0814)					  | 0x0003));			bcm43xx_phy_write(bcm, 0x0815,			                  (bcm43xx_phy_read(bcm, 0x0815)					  & 0xFFFC));			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,			                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)					  & 0x7FFF));			bcm43xx_phy_write(bcm, 0x0802,			                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));			if (phy->rev > 1) { /* loopback gain enabled */				backup[19] = bcm43xx_phy_read(bcm, 0x080F);				backup[20] = bcm43xx_phy_read(bcm, 0x0810);				if (phy->rev >= 3)					bcm43xx_phy_write(bcm, 0x080F, 0xC020);				else					bcm43xx_phy_write(bcm, 0x080F, 0x8020);				bcm43xx_phy_write(bcm, 0x0810, 0x0000);			}			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));			if (phy->rev < 7 || !(bcm->sprom.boardflags			    & BCM43xx_BFL_EXTLNA))				bcm43xx_phy_write(bcm, 0x0811, 0x01B3);			else				bcm43xx_phy_write(bcm, 0x0811, 0x09B3);		}	}	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,	                (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));	backup[10] = bcm43xx_phy_read(bcm, 0x0035);	bcm43xx_phy_write(bcm, 0x0035,	                  (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));	backup[11] = bcm43xx_read16(bcm, 0x03E6);	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);	// Initialization	if (phy->analog == 0) {		bcm43xx_write16(bcm, 0x03E6, 0x0122);	} else {		if (phy->analog >= 2)			bcm43xx_phy_write(bcm, 0x0003,					  (bcm43xx_phy_read(bcm, 0x0003)					  & 0xFFBF) | 0x0040);		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)				| 0x2000));	}	ret = bcm43xx_radio_calibrationvalue(bcm);	if (phy->type == BCM43xx_PHYTYPE_B)		bcm43xx_radio_write16(bcm, 0x0078, 0x0026);	if (phy->connected)		bcm43xx_phy_write(bcm, 0x0812,				  bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);	bcm43xx_phy_write(bcm, 0x002B, 0x1403);	if (phy->connected)		bcm43xx_phy_write(bcm, 0x0812,				  bcm43xx_get_812_value(bcm, LPD(0, 0, 1)));	bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);	bcm43xx_radio_write16(bcm, 0x0051,	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));	if (radio->revision == 8)		bcm43xx_radio_write16(bcm, 0x0043, 0x001F);	else {		bcm43xx_radio_write16(bcm, 0x0052, 0x0000);		bcm43xx_radio_write16(bcm, 0x0043,				      (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0)				      | 0x0009);	}	bcm43xx_phy_write(bcm, 0x0058, 0x0000);	for (i = 0; i < 16; i++) {		bcm43xx_phy_write(bcm, 0x005A, 0x0480);		bcm43xx_phy_write(bcm, 0x0059, 0xC810);		bcm43xx_phy_write(bcm, 0x0058, 0x000D);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);		udelay(10);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));		bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);		udelay(10);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_get_812_value(bcm, LPD(1, 0, 0)));		bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);		udelay(20);		tmp1 += bcm43xx_phy_read(bcm, 0x002D);		bcm43xx_phy_write(bcm, 0x0058, 0x0000);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);	}	tmp1++;	tmp1 >>= 9;	udelay(10);	bcm43xx_phy_write(bcm, 0x0058, 0x0000);	for (i = 0; i < 16; i++) {		bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);		backup[13] = bcm43xx_radio_read16(bcm, 0x0078);		udelay(10);		for (j = 0; j < 16; j++) {			bcm43xx_phy_write(bcm, 0x005A, 0x0D80);			bcm43xx_phy_write(bcm, 0x0059, 0xC810);			bcm43xx_phy_write(bcm, 0x0058, 0x000D);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812,						  bcm43xx_get_812_value(bcm,						  LPD(1, 0, 1)));			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);			udelay(10);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812,						  bcm43xx_get_812_value(bcm,						  LPD(1, 0, 1)));			bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);			udelay(10);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812,						  bcm43xx_get_812_value(bcm,						  LPD(1, 0, 0)));			bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);			udelay(10);			tmp2 += bcm43xx_phy_read(bcm, 0x002D);			bcm43xx_phy_write(bcm, 0x0058, 0x0000);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812,						  bcm43xx_get_812_value(bcm,						  LPD(1, 0, 1)));			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);		}		tmp2++;		tmp2 >>= 8;		if (tmp1 < tmp2)			break;	}	/* Restore the registers */	bcm43xx_phy_write(bcm, 0x0015, backup[1]);	bcm43xx_radio_write16(bcm, 0x0051, backup[14]);	bcm43xx_radio_write16(bcm, 0x0052, backup[15]);	bcm43xx_radio_write16(bcm, 0x0043, backup[0]);	bcm43xx_phy_write(bcm, 0x005A, backup[16]);	bcm43xx_phy_write(bcm, 0x0059, backup[17]);	bcm43xx_phy_write(bcm, 0x0058, backup[18]);	bcm43xx_write16(bcm, 0x03E6, backup[11]);	if (phy->analog != 0)		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);	bcm43xx_phy_write(bcm, 0x0035, backup[10]);	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);	if (phy->type == BCM43xx_PHYTYPE_B) {		bcm43xx_phy_write(bcm, 0x0030, backup[2]);		bcm43xx_write16(bcm, 0x03EC, backup[3]);	} else {		if (phy->connected) {			bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,					(bcm43xx_read16(bcm,					BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));			bcm43xx_phy_write(bcm, 0x0811, backup[4]);			bcm43xx_phy_write(bcm, 0x0812, backup[5]);			bcm43xx_phy_write(bcm, 0x0814, backup[6]);			bcm43xx_phy_write(bcm, 0x0815, backup[7]);			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);			bcm43xx_phy_write(bcm, 0x0802, backup[9]);			if (phy->rev > 1) {				bcm43xx_phy_write(bcm, 0x080F, backup[19]);				bcm43xx_phy_write(bcm, 0x0810, backup[20]);			}		}	}	if (i >= 15)		ret = backup[13];	return ret;}void bcm43xx_radio_init2060(struct bcm43xx_private *bcm){	int err;	bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);	bcm43xx_radio_write16(bcm, 0x0005, 0x0008);	bcm43xx_radio_write16(bcm, 0x0009, 0x0040);	bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);	bcm43xx_radio_write16(bcm, 0x0032, 0x008F);	bcm43xx_radio_write16(bcm, 0x0006, 0x008F);	bcm43xx_radio_write16(bcm, 0x0034, 0x008F);	bcm43xx_radio_write16(bcm, 0x002C, 0x0007);	bcm43xx_radio_write16(bcm, 0x0082, 0x0080);	bcm43xx_radio_write16(bcm, 0x0080, 0x0000);	bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);	udelay(400);	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);	udelay(400);	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);	bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);	bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);	bcm43xx_phy_write(bcm, 0x0069, 0x07BE);	bcm43xx_phy_write(bcm, 0x006A, 0x0000);	err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);	assert(err == 0);	udelay(1000);}static inlineu16 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 bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm){	static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };	static const u8 data_low[5]  = { 0x00, 0x01, 0x05, 0x06, 0x0A };	u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);	int i, j;		for (i = 0; i < 5; i++) {		for (j = 0; j < 5; j++) {			if (tmp == (data_high[i] | data_low[j])) {				bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);				return;			}		}	}}int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,				u8 channel,				int synthetic_pu_workaround){	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 r8, tmp;	u16 freq;

⌨️ 快捷键说明

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