aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/debugfs.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 53b0b7711f02..0a0cc9667cd6 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -402,24 +402,28 @@ static const struct file_operations iwm_debugfs_txq_fops = {
402 .owner = THIS_MODULE, 402 .owner = THIS_MODULE,
403 .open = iwm_generic_open, 403 .open = iwm_generic_open,
404 .read = iwm_debugfs_txq_read, 404 .read = iwm_debugfs_txq_read,
405 .llseek = default_llseek,
405}; 406};
406 407
407static const struct file_operations iwm_debugfs_tx_credit_fops = { 408static const struct file_operations iwm_debugfs_tx_credit_fops = {
408 .owner = THIS_MODULE, 409 .owner = THIS_MODULE,
409 .open = iwm_generic_open, 410 .open = iwm_generic_open,
410 .read = iwm_debugfs_tx_credit_read, 411 .read = iwm_debugfs_tx_credit_read,
412 .llseek = default_llseek,
411}; 413};
412 414
413static const struct file_operations iwm_debugfs_rx_ticket_fops = { 415static const struct file_operations iwm_debugfs_rx_ticket_fops = {
414 .owner = THIS_MODULE, 416 .owner = THIS_MODULE,
415 .open = iwm_generic_open, 417 .open = iwm_generic_open,
416 .read = iwm_debugfs_rx_ticket_read, 418 .read = iwm_debugfs_rx_ticket_read,
419 .llseek = default_llseek,
417}; 420};
418 421
419static const struct file_operations iwm_debugfs_fw_err_fops = { 422static const struct file_operations iwm_debugfs_fw_err_fops = {
420 .owner = THIS_MODULE, 423 .owner = THIS_MODULE,
421 .open = iwm_generic_open, 424 .open = iwm_generic_open,
422 .read = iwm_debugfs_fw_err_read, 425 .read = iwm_debugfs_fw_err_read,
426 .llseek = default_llseek,
423}; 427};
424 428
425void iwm_debugfs_init(struct iwm_priv *iwm) 429void iwm_debugfs_init(struct iwm_priv *iwm)
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
/*
 * This is part of the rtl8180-sa2400 driver
 * released under the GPL (See file COPYING for details).
 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
 *
 * This files contains programming code for the rtl8225
 * radio frontend.
 *
 * *Many* thanks to Realtek Corp. for their great support!
 */

#include "r8180_hw.h"
#include "r8180_rtl8225.h"
#include "r8180_93cx6.h"

#include "ieee80211/dot11d.h"

static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
{
	int i;
	u16 out, select;
	u8 bit;
	u32 bangdata = (data << 4) | (adr & 0xf);

	out = read_nic_word(dev, RFPinsOutput) & 0xfff3;

	write_nic_word(dev, RFPinsEnable,
		(read_nic_word(dev, RFPinsEnable) | 0x7));

	select = read_nic_word(dev, RFPinsSelect);

	write_nic_word(dev, RFPinsSelect, select | 0x7 |
		       SW_CONTROL_GPIO);

	force_pci_posting(dev);
	udelay(10);

	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);

	force_pci_posting(dev);
	udelay(2);

	write_nic_word(dev, RFPinsOutput, out);

	force_pci_posting(dev);
	udelay(10);

	for (i = 15; i >= 0; i--) {
		bit = (bangdata & (1 << i)) >> i;

		write_nic_word(dev, RFPinsOutput, bit | out);

		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);

		i--;
		bit = (bangdata & (1 << i)) >> i;

		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);

		write_nic_word(dev, RFPinsOutput, bit | out);

	}

	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);

	force_pci_posting(dev);
	udelay(10);

	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);

	write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);

	rtl8185_rf_pins_enable(dev);
}

static const u8 rtl8225_agc[] = {
	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
};

static const u32 rtl8225_chan[] = {
	0,
	0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
	0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
};

static const u8 rtl8225z2_gain_bg[] = {
	0x23, 0x15, 0xa5, /* -82-1dBm */
	0x23, 0x15, 0xb5, /* -82-2dBm */
	0x23, 0x15, 0xc5, /* -82-3dBm */
	0x33, 0x15, 0xc5, /* -78dBm */
	0x43, 0x15, 0xc5, /* -74dBm */
	0x53, 0x15, 0xc5, /* -70dBm */
	0x63, 0x15, 0xc5, /* -66dBm */
};

static const u8 rtl8225z2_gain_a[] = {
	0x13, 0x27, 0x5a, /* -82dBm */
	0x23, 0x23, 0x58, /* -82dBm */
	0x33, 0x1f, 0x56, /* -82dBm */
	0x43, 0x1b, 0x54, /* -78dBm */
	0x53, 0x17, 0x51, /* -74dBm */
	0x63, 0x24, 0x4f, /* -70dBm */
	0x73, 0x0f, 0x4c, /* -66dBm */
};

static const u16 rtl8225z2_rxgain[] = {
	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb

};

void rtl8225z2_set_gain(struct net_device *dev, short gain)
{
	const u8 *rtl8225_gain;
	struct r8180_priv *priv = ieee80211_priv(dev);
	u8 mode = priv->ieee80211->mode;

	if (mode == IEEE_B || mode == IEEE_G)
		rtl8225_gain = rtl8225z2_gain_bg;
	else
		rtl8225_gain = rtl8225z2_gain_a;

	write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
	write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
	write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
	write_phy_ofdm(dev, 0x21, 0x37);
}

static u32 read_rtl8225(struct net_device *dev, u8 adr)
{
	u32 data2Write = ((u32)(adr & 0x1f)) << 27;
	u32 dataRead;
	u32 mask;
	u16 oval, oval2, oval3, tmp;
	int i;
	short bit, rw;
	u8 wLength = 6;
	u8 rLength = 12;
	u8 low2high = 0;

	oval = read_nic_word(dev, RFPinsOutput);
	oval2 = read_nic_word(dev, RFPinsEnable);
	oval3 = read_nic_word(dev, RFPinsSelect);

	write_nic_word(dev, RFPinsEnable, (oval2|0xf));
	write_nic_word(dev, RFPinsSelect, (oval3|0xf));

	dataRead = 0;

	oval &= ~0xf;

	write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
	udelay(4);

	write_nic_word(dev, RFPinsOutput, oval);
	udelay(5);

	rw = 0;

	mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));

	for (i = 0; i < wLength/2; i++) {
		bit = ((data2Write&mask) != 0) ? 1 : 0;
		write_nic_word(dev, RFPinsOutput, bit | oval | rw);
		udelay(1);

		write_nic_word(dev, RFPinsOutput,
				bit | oval | BB_HOST_BANG_CLK | rw);
		udelay(2);
		write_nic_word(dev, RFPinsOutput,
				bit | oval | BB_HOST_BANG_CLK | rw);
		udelay(2);

		mask = (low2high) ? (mask<<1) : (mask>>1);

		if (i == 2) {
			rw = BB_HOST_BANG_RW;
			write_nic_word(dev, RFPinsOutput,
					bit | oval | BB_HOST_BANG_CLK | rw);
			udelay(2);
			write_nic_word(dev, RFPinsOutput, bit | oval | rw);
			udelay(2);
			break;
		}

		bit = ((data2Write&mask) != 0) ? 1 : 0;

		write_nic_word(dev, RFPinsOutput,
				oval | bit | rw | BB_HOST_BANG_CLK);
		udelay(2);
		write_nic_word(dev, RFPinsOutput,
				oval | bit | rw | BB_HOST_BANG_CLK);
		udelay(2);

		write_nic_word(dev, RFPinsOutput, oval | bit | rw);
		udelay(1);

		mask = (low2high) ? (mask<<1) : (mask>>1);
	}

	write_nic_word(dev, RFPinsOutput, rw|oval);
	udelay(2);
	mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));

	/*
	 * We must set data pin to HW controlled, otherwise RF can't driver it
	 * and value RF register won't be able to read back properly.
	 */
	write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));

	for (i = 0; i < rLength; i++) {
		write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);

		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
		udelay(2);
		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
		udelay(2);
		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
		udelay(2);
		tmp = read_nic_word(dev, RFPinsInput);

		dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);

		write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);

		mask = (low2high) ? (mask<<1) : (mask>>1);
	}

	write_nic_word(dev, RFPinsOutput,
			BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
	udelay(2);

	write_nic_word(dev, RFPinsEnable, oval2);
	write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
	write_nic_word(dev, RFPinsOutput, 0x3a0);

	return dataRead;
}

void rtl8225z2_rf_close(struct net_device *dev)
{
	RF_WriteReg(dev, 0x4, 0x1f);

	force_pci_posting(dev);
	mdelay(1);

	rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
	rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
}

/*
 * Map dBm into Tx power index according to current HW model, for example,
 * RF and PA, and current wireless mode.
 */
s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode,
		 s32 PowerInDbm)
{
	bool bUseDefault = true;
	s8 TxPwrIdx = 0;

	/*
	 * OFDM Power in dBm = Index * 0.5 + 0
	 * CCK Power in dBm = Index * 0.25 + 13
	 */
	s32 tmp = 0;

	if (WirelessMode == WIRELESS_MODE_G) {
		bUseDefault = false;
		tmp = (2 * PowerInDbm);

		if (tmp < 0)
			TxPwrIdx = 0;
		else if (tmp > 40) /* 40 means 20 dBm. */
			TxPwrIdx = 40;
		else
			TxPwrIdx = (s8)tmp;
	} else if (WirelessMode == WIRELESS_MODE_B) {
		bUseDefault = false;
		tmp = (4 * PowerInDbm) - 52;

		if (tmp < 0)
			TxPwrIdx = 0;
		else if (tmp > 28) /* 28 means 20 dBm. */
			TxPwrIdx = 28;
		else
			TxPwrIdx = (s8)tmp;
	}

	/*
	 * TRUE if we want to use a default implementation.
	 * We shall set it to FALSE when we have exact translation formula
	 * for target IC. 070622, by rcnjko.
	 */
	if (bUseDefault) {
		if (PowerInDbm < 0)
			TxPwrIdx = 0;
		else if (PowerInDbm > 35)
			TxPwrIdx = 35;
		else
			TxPwrIdx = (u8)PowerInDbm;
	}

	return TxPwrIdx;
}

void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
{
	struct r8180_priv *priv = ieee80211_priv(dev);
	u8 max_cck_power_level;
	u8 max_ofdm_power_level;
	u8 min_ofdm_power_level;
	char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
	char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);

	if (IS_DOT11D_ENABLE(priv->ieee80211) &&
	    IS_DOT11D_STATE_DONE(priv->ieee80211)) {
		u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
		u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
							MaxTxPwrInDbm);
		u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
							MaxTxPwrInDbm);

		if (cck_power_level > CckMaxPwrIdx)
			cck_power_level = CckMaxPwrIdx;
		if (ofdm_power_level > OfdmMaxPwrIdx)
			ofdm_power_level = OfdmMaxPwrIdx;
	}

	max_cck_power_level = 15;
	max_ofdm_power_level = 25;
	min_ofdm_power_level = 10;

	if (cck_power_level > 35)
		cck_power_level = 35;

	write_nic_byte(dev, CCK_TXAGC, cck_power_level);
	force_pci_posting(dev);
	mdelay(1);

	if (ofdm_power_level > 35)
		ofdm_power_level = 35;

	if (priv->up == 0) {
		write_phy_ofdm(dev, 2, 0x42);