diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800.h | 52 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 330 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 73 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.h | 31 |
17 files changed, 516 insertions, 220 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a252..6458ab87717b 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -205,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - return rt2x00_get_field32(reg, GPIOCSR_BIT0); + return rt2x00_get_field32(reg, GPIOCSR_VAL0); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1624,6 +1625,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + + /* * Initialize hw specifications. */ retval = rt2400pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc439..e4b07f0aa3cc 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -660,16 +660,26 @@ /* * GPIOCSR: GPIO control register. + * GPIOCSR_VALx: Actual GPIO pin x value + * GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input */ #define GPIOCSR 0x0120 -#define GPIOCSR_BIT0 FIELD32(0x00000001) -#define GPIOCSR_BIT1 FIELD32(0x00000002) -#define GPIOCSR_BIT2 FIELD32(0x00000004) -#define GPIOCSR_BIT3 FIELD32(0x00000008) -#define GPIOCSR_BIT4 FIELD32(0x00000010) -#define GPIOCSR_BIT5 FIELD32(0x00000020) -#define GPIOCSR_BIT6 FIELD32(0x00000040) -#define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_VAL0 FIELD32(0x00000001) +#define GPIOCSR_VAL1 FIELD32(0x00000002) +#define GPIOCSR_VAL2 FIELD32(0x00000004) +#define GPIOCSR_VAL3 FIELD32(0x00000008) +#define GPIOCSR_VAL4 FIELD32(0x00000010) +#define GPIOCSR_VAL5 FIELD32(0x00000020) +#define GPIOCSR_VAL6 FIELD32(0x00000040) +#define GPIOCSR_VAL7 FIELD32(0x00000080) +#define GPIOCSR_DIR0 FIELD32(0x00000100) +#define GPIOCSR_DIR1 FIELD32(0x00000200) +#define GPIOCSR_DIR2 FIELD32(0x00000400) +#define GPIOCSR_DIR3 FIELD32(0x00000800) +#define GPIOCSR_DIR4 FIELD32(0x00001000) +#define GPIOCSR_DIR5 FIELD32(0x00002000) +#define GPIOCSR_DIR6 FIELD32(0x00004000) +#define GPIOCSR_DIR7 FIELD32(0x00008000) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b5..68bca1456cda 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -205,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - return rt2x00_get_field32(reg, GPIOCSR_BIT0); + return rt2x00_get_field32(reg, GPIOCSR_VAL0); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1942,6 +1943,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + + /* * Initialize hw specifications. */ retval = rt2500pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 2aad7ba8a100..9c10068e4987 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -789,16 +789,18 @@ /* * GPIOCSR: GPIO control register. + * GPIOCSR_VALx: GPIO value + * GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input */ #define GPIOCSR 0x0120 -#define GPIOCSR_BIT0 FIELD32(0x00000001) -#define GPIOCSR_BIT1 FIELD32(0x00000002) -#define GPIOCSR_BIT2 FIELD32(0x00000004) -#define GPIOCSR_BIT3 FIELD32(0x00000008) -#define GPIOCSR_BIT4 FIELD32(0x00000010) -#define GPIOCSR_BIT5 FIELD32(0x00000020) -#define GPIOCSR_BIT6 FIELD32(0x00000040) -#define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_VAL0 FIELD32(0x00000001) +#define GPIOCSR_VAL1 FIELD32(0x00000002) +#define GPIOCSR_VAL2 FIELD32(0x00000004) +#define GPIOCSR_VAL3 FIELD32(0x00000008) +#define GPIOCSR_VAL4 FIELD32(0x00000010) +#define GPIOCSR_VAL5 FIELD32(0x00000020) +#define GPIOCSR_VAL6 FIELD32(0x00000040) +#define GPIOCSR_VAL7 FIELD32(0x00000080) #define GPIOCSR_DIR0 FIELD32(0x00000100) #define GPIOCSR_DIR1 FIELD32(0x00000200) #define GPIOCSR_DIR2 FIELD32(0x00000400) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9e..f95b5516c50a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_VAL7); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_DIR0, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + + /* * Initialize hw specifications. */ retval = rt2500usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7eed..1b91a4cef965 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -187,16 +187,26 @@ /* * MAC_CSR19: GPIO control register. + * MAC_CSR19_VALx: GPIO value + * MAC_CSR19_DIRx: GPIO direction: 0 = input; 1 = output */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_VAL0 FIELD16(0x0001) +#define MAC_CSR19_VAL1 FIELD16(0x0002) +#define MAC_CSR19_VAL2 FIELD16(0x0004) +#define MAC_CSR19_VAL3 FIELD16(0x0008) +#define MAC_CSR19_VAL4 FIELD16(0x0010) +#define MAC_CSR19_VAL5 FIELD16(0x0020) +#define MAC_CSR19_VAL6 FIELD16(0x0040) +#define MAC_CSR19_VAL7 FIELD16(0x0080) +#define MAC_CSR19_DIR0 FIELD16(0x0100) +#define MAC_CSR19_DIR1 FIELD16(0x0200) +#define MAC_CSR19_DIR2 FIELD16(0x0400) +#define MAC_CSR19_DIR3 FIELD16(0x0800) +#define MAC_CSR19_DIR4 FIELD16(0x1000) +#define MAC_CSR19_DIR5 FIELD16(0x2000) +#define MAC_CSR19_DIR6 FIELD16(0x4000) +#define MAC_CSR19_DIR7 FIELD16(0x8000) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index e252e9bafd0e..6d67c3ede651 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -439,26 +439,33 @@ #define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) /* - * GPIO_CTRL_CFG: - * GPIOD: GPIO direction, 0: Output, 1: Input - */ -#define GPIO_CTRL_CFG 0x0228 -#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) -#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) -#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) -#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) -#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) -#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) -#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) -#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) -#define GPIO_CTRL_CFG_GPIOD_BIT0 FIELD32(0x00000100) -#define GPIO_CTRL_CFG_GPIOD_BIT1 FIELD32(0x00000200) -#define GPIO_CTRL_CFG_GPIOD_BIT2 FIELD32(0x00000400) -#define GPIO_CTRL_CFG_GPIOD_BIT3 FIELD32(0x00000800) -#define GPIO_CTRL_CFG_GPIOD_BIT4 FIELD32(0x00001000) -#define GPIO_CTRL_CFG_GPIOD_BIT5 FIELD32(0x00002000) -#define GPIO_CTRL_CFG_GPIOD_BIT6 FIELD32(0x00004000) -#define GPIO_CTRL_CFG_GPIOD_BIT7 FIELD32(0x00008000) + * GPIO_CTRL: + * GPIO_CTRL_VALx: GPIO value + * GPIO_CTRL_DIRx: GPIO direction: 0 = output; 1 = input + */ +#define GPIO_CTRL 0x0228 +#define GPIO_CTRL_VAL0 FIELD32(0x00000001) +#define GPIO_CTRL_VAL1 FIELD32(0x00000002) +#define GPIO_CTRL_VAL2 FIELD32(0x00000004) +#define GPIO_CTRL_VAL3 FIELD32(0x00000008) +#define GPIO_CTRL_VAL4 FIELD32(0x00000010) +#define GPIO_CTRL_VAL5 FIELD32(0x00000020) +#define GPIO_CTRL_VAL6 FIELD32(0x00000040) +#define GPIO_CTRL_VAL7 FIELD32(0x00000080) +#define GPIO_CTRL_DIR0 FIELD32(0x00000100) +#define GPIO_CTRL_DIR1 FIELD32(0x00000200) +#define GPIO_CTRL_DIR2 FIELD32(0x00000400) +#define GPIO_CTRL_DIR3 FIELD32(0x00000800) +#define GPIO_CTRL_DIR4 FIELD32(0x00001000) +#define GPIO_CTRL_DIR5 FIELD32(0x00002000) +#define GPIO_CTRL_DIR6 FIELD32(0x00004000) +#define GPIO_CTRL_DIR7 FIELD32(0x00008000) +#define GPIO_CTRL_VAL8 FIELD32(0x00010000) +#define GPIO_CTRL_VAL9 FIELD32(0x00020000) +#define GPIO_CTRL_VAL10 FIELD32(0x00040000) +#define GPIO_CTRL_DIR8 FIELD32(0x01000000) +#define GPIO_CTRL_DIR9 FIELD32(0x02000000) +#define GPIO_CTRL_DIR10 FIELD32(0x04000000) /* * MCU_CMD_CFG @@ -1936,6 +1943,11 @@ struct mac_iveiv_entry { #define BBP47_TSSI_ADC6 FIELD8(0x80) /* + * BBP 49 + */ +#define BBP49_UPDATE_FLAG FIELD8(0x01) + +/* * BBP 109 */ #define BBP109_TX0_POWER FIELD8(0x0f) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e4..9e09367c9739 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -923,8 +923,8 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); } else { - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + return rt2x00_get_field32(reg, GPIO_CTRL_VAL2); } } EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); @@ -1570,10 +1570,10 @@ static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev, rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff, eesk_pin, 0); - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT3, 0); - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT3, gpio_bit3); - rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); + rt2x00_set_field32(®, GPIO_CTRL_VAL3, gpio_bit3); + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); } void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) @@ -1615,6 +1615,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) case 1: if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3390)) { rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); @@ -1995,13 +1996,13 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); } - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT7, 0); + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); if (rf->channel <= 14) - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 1); + rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); else - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 0); - rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + rt2x00_set_field32(®, GPIO_CTRL_VAL7, 0); + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); @@ -2053,6 +2054,60 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, } } +static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + + rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); + rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); + + rt2800_rfcsr_write(rt2x00dev, 11, 0x42); + rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); + rt2800_rfcsr_write(rt2x00dev, 13, 0x00); + + if (info->default_power1 > POWER_BOUND) + rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND); + else + rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1); + + if (info->default_power2 > POWER_BOUND) + rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND); + else + rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); + + rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); + if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); + else + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); + + rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); + + if ( rt2x00dev->default_ant.tx_chain_num == 2 ) + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + else + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + + if ( rt2x00dev->default_ant.rx_chain_num == 2 ) + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + else + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 31, 80); +} + static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, struct rf_channel *rf, @@ -2182,6 +2237,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, case RF3290: rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); break; + case RF3322: + rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); + break; case RF5360: case RF5370: case RF5372: @@ -2194,6 +2252,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } if (rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || @@ -2212,10 +2271,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, /* * Change BBP settings */ - rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 86, 0); + if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_write(rt2x00dev, 27, 0x0); + rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 27, 0x20); + rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain); + } else { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 86, 0); + } if (rf->channel <= 14) { if (!rt2x00_rt(rt2x00dev, RT5390) && @@ -2310,6 +2376,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®); rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®); rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); + + /* + * Clear update flag + */ + if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_read(rt2x00dev, 49, &bbp); + rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); + rt2800_bbp_write(rt2x00dev, 49, bbp); + } } static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) @@ -2998,6 +3073,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); + } else if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); } else if (rt2x00_rt(rt2x00dev, RT3572)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -3378,6 +3457,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_wait_bbp_ready(rt2x00dev))) return -EACCES; + if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_write(rt2x00dev, 3, 0x00); + rt2800_bbp_write(rt2x00dev, 4, 0x50); + } + if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) { @@ -3388,15 +3472,20 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2800_is_305x_soc(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 31, 0x08); + if (rt2x00_rt(rt2x00dev, RT3352)) + rt2800_bbp_write(rt2x00dev, 47, 0x48); + rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 68, 0x0b); @@ -3405,6 +3494,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 73, 0x12); } else if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) { rt2800_bbp_write(rt2x00dev, 69, 0x12); @@ -3436,6 +3526,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } else if (rt2800_is_305x_soc(rt2x00dev)) { rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); + } else if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_write(rt2x00dev, 78, 0x0e); + rt2800_bbp_write(rt2x00dev, 80, 0x08); + rt2800_bbp_write(rt2x00dev, 81, 0x37); } else { rt2800_bbp_write(rt2x00dev, 81, 0x37); } @@ -3465,18 +3559,21 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 86, 0x38); else rt2800_bbp_write(rt2x00dev, 86, 0x00); - if (rt2x00_rt(rt2x00dev, RT5392)) + if (rt2x00_rt(rt2x00dev, RT3352) || + rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 88, 0x90); rt2800_bbp_write(rt2x00dev, 91, 0x04); if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 92, 0x02); @@ -3493,6 +3590,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392) || @@ -3502,6 +3600,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); if (rt2x00_rt(rt2x00dev, RT3290) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 104, 0x92); @@ -3510,6 +3609,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x01); else if (rt2x00_rt(rt2x00dev, RT3290)) rt2800_bbp_write(rt2x00dev, 105, 0x1c); + else if (rt2x00_rt(rt2x00dev, RT3352)) + rt2800_bbp_write(rt2x00dev, 105, 0x34); else if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 105, 0x3c); @@ -3519,11 +3620,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390)) rt2800_bbp_write(rt2x00dev, 106, 0x03); + else if (rt2x00_rt(rt2x00dev, RT3352)) + rt2800_bbp_write(rt2x00dev, 106, 0x05); else if (rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 106, 0x12); else rt2800_bbp_write(rt2x00dev, 106, 0x35); + if (rt2x00_rt(rt2x00dev, RT3352)) + rt2800_bbp_write(rt2x00dev, 120, 0x50); + if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) @@ -3534,6 +3640,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 135, 0xf6); } + if (rt2x00_rt(rt2x00dev, RT3352)) + rt2800_bbp_write(rt2x00dev, 137, 0x0f); + if (rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3390) || @@ -3574,6 +3683,28 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 3, value); } + if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_write(rt2x00dev, 163, 0xbd); + /* Set ITxBF timeout to 0x9c40=1000msec */ + rt2800_bbp_write(rt2x00dev, 179, 0x02); + rt2800_bbp_write(rt2x00dev, 180, 0x00); + rt2800_bbp_write(rt2x00dev, 182, 0x40); + rt2800_bbp_write(rt2x00dev, 180, 0x01); + rt2800_bbp_write(rt2x00dev, 182, 0x9c); + rt2800_bbp_write(rt2x00dev, 179, 0x00); + /* Reprogram the inband interface to put right values in RXWI */ + rt2800_bbp_write(rt2x00dev, 142, 0x04); + rt2800_bbp_write(rt2x00dev, 143, 0x3b); + rt2800_bbp_write(rt2x00dev, 142, 0x06); + rt2800_bbp_write(rt2x00dev, 143, 0xa0); + rt2800_bbp_write(rt2x00dev, 142, 0x07); + rt2800_bbp_write(rt2x00dev, 143, 0xa1); + rt2800_bbp_write(rt2x00dev, 142, 0x08); + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + + rt2800_bbp_write(rt2x00dev, 148, 0xc8); + } + if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) { int ant, div_mode; @@ -3587,16 +3718,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { u32 reg; - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT3, 0); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT6, 0); - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT3, 0); - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT6, 0); + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); + rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0); + rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0); + rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0); if (ant == 0) - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT3, 1); + rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1); else if (ant == 1) - rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT6, 1); - rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1); + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); } /* This chip has hardware antenna diversity*/ @@ -3707,6 +3838,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) !rt2x00_rt(rt2x00dev, RT3071) && !rt2x00_rt(rt2x00dev, RT3090) && !rt2x00_rt(rt2x00dev, RT3290) && + !rt2x00_rt(rt2x00dev, RT3352) && !rt2x00_rt(rt2x00dev, RT3390) && !rt2x00_rt(rt2x00dev, RT3572) && !rt2x00_rt(rt2x00dev, RT5390) && @@ -3903,6 +4035,70 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 30, 0x00); rt2800_rfcsr_write(rt2x00dev, 31, 0x00); return 0; + } else if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); + rt2800_rfcsr_write(rt2x00dev, 1, 0x23); + rt2800_rfcsr_write(rt2x00dev, 2, 0x50); + rt2800_rfcsr_write(rt2x00dev, 3, 0x18); + rt2800_rfcsr_write(rt2x00dev, 4, 0x00); + rt2800_rfcsr_write(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write(rt2x00dev, 6, 0x33); + rt2800_rfcsr_write(rt2x00dev, 7, 0x00); + rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); + rt2800_rfcsr_write(rt2x00dev, 9, 0x02); + rt2800_rfcsr_write(rt2x00dev, 10, 0xd2); + rt2800_rfcsr_write(rt2x00dev, 11, 0x42); + rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); + rt2800_rfcsr_write(rt2x00dev, 13, 0x00); + rt2800_rfcsr_write(rt2x00dev, 14, 0x5a); + rt2800_rfcsr_write(rt2x00dev, 15, 0x00); + rt2800_rfcsr_write(rt2x00dev, 16, 0x01); + rt2800_rfcsr_write(rt2x00dev, 18, 0x45); + rt2800_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800_rfcsr_write(rt2x00dev, 20, 0x00); + rt2800_rfcsr_write(rt2x00dev, 21, 0x00); + rt2800_rfcsr_write(rt2x00dev, 22, 0x00); + rt2800_rfcsr_write(rt2x00dev, 23, 0x00); + rt2800_rfcsr_write(rt2x00dev, 24, 0x00); + rt2800_rfcsr_write(rt2x00dev, 25, 0x80); + rt2800_rfcsr_write(rt2x00dev, 26, 0x00); + rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + rt2800_rfcsr_write(rt2x00dev, 28, 0x03); + rt2800_rfcsr_write(rt2x00dev, 29, 0x00); + rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); + rt2800_rfcsr_write(rt2x00dev, 34, 0x01); + rt2800_rfcsr_write(rt2x00dev, 35, 0x03); + rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); + rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); + rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); + rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); + rt2800_rfcsr_write(rt2x00dev, 40, 0x33); + rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); + rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); + rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 46, 0xdd); + rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); + rt2800_rfcsr_write(rt2x00dev, 48, 0x14); + rt2800_rfcsr_write(rt2x00dev, 49, 0x00); + rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); + rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); + rt2800_rfcsr_write(rt2x00dev, 52, 0x00); + rt2800_rfcsr_write(rt2x00dev, 53, 0x52); + rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); + rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); + rt2800_rfcsr_write(rt2x00dev, 56, 0x00); + rt2800_rfcsr_write(rt2x00dev, 57, 0x52); + rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); + rt2800_rfcsr_write(rt2x00dev, 59, 0x00); + rt2800_rfcsr_write(rt2x00dev, 60, 0x00); + rt2800_rfcsr_write(rt2x00dev, 61, 0x00); + rt2800_rfcsr_write(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write(rt2x00dev, 63, 0x00); } else if (rt2x00_rt(rt2x00dev, RT5390)) { rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); rt2800_rfcsr_write(rt2x00dev, 2, 0x80); @@ -4089,6 +4285,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, LDO_CFG0, reg); msleep(1); rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } @@ -4103,6 +4300,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); } else if (rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3390) || rt2x00_rt(rt2x00dev, RT3572)) { drv_data->calibration_bw20 = @@ -4391,7 +4589,7 @@ void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); -int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u16 word; @@ -4399,6 +4597,11 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) u8 default_lna_gain; /* + * Read the EEPROM. + */ + rt2800_read_eeprom(rt2x00dev); + + /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); @@ -4520,9 +4723,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); -int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; u16 value; @@ -4561,6 +4763,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RT3071: case RT3090: case RT3290: + case RT3352: case RT3390: case RT3572: case RT5390: @@ -4583,6 +4786,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF3052: case RF3290: case RF3320: + case RF3322: case RF5360: case RF5370: case RF5372: @@ -4607,6 +4811,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3390)) { value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); @@ -4680,7 +4885,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_init_eeprom); /* * RF value list for rt28xx @@ -4823,7 +5027,7 @@ static const struct rf_channel rf_vals_3x[] = { {173, 0x61, 0, 9}, }; -int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) +static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; @@ -4900,6 +5104,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00_rf(rt2x00dev, RF3022) || rt2x00_rf(rt2x00dev, RF3290) || rt2x00_rf(rt2x00dev, RF3320) || + rt2x00_rf(rt2x00dev, RF3322) || rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || @@ -4999,7 +5204,72 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) return 0; } -EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode); + +int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) +{ + int retval; + u32 reg; + + /* + * Allocate eeprom data. + */ + retval = rt2800_validate_eeprom(rt2x00dev); + if (retval) + return retval; + + retval = rt2800_init_eeprom(rt2x00dev); + if (retval) + return retval; + + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + rt2x00_set_field32(®, GPIO_CTRL_DIR2, 1); + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + + /* + * Initialize hw specifications. + */ + retval = rt2800_probe_hw_mode(rt2x00dev); + if (retval) + return retval; + + /* + * Set device capabilities. + */ + __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); + if (!rt2x00_is_usb(rt2x00dev)) + __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); + + /* + * Set device requirements. + */ + if (!rt2x00_is_soc(rt2x00dev)) + __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); + if (!rt2800_hwcrypt_disabled(rt2x00dev)) + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); + if (rt2x00_is_usb(rt2x00dev)) + __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); + else { + __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); + } + + /* + * Set the rssi offset. + */ + rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + + return 0; +} +EXPORT_SYMBOL_GPL(rt2800_probe_hw); /* * IEEE80211 stack callback functions. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 18a0b67b4c68..a128ceadcb3e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -43,6 +43,9 @@ struct rt2800_ops { const unsigned int offset, const struct rt2x00_field32 field, u32 *reg); + void (*read_eeprom)(struct rt2x00_dev *rt2x00dev); + bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev); + int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len); int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); @@ -114,6 +117,20 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); } +static inline void rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) +{ + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + + rt2800ops->read_eeprom(rt2x00dev); +} + +static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + + return rt2800ops->hwcrypt_disabled(rt2x00dev); +} + static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { @@ -191,9 +208,8 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); -int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev); -int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev); -int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); + +int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev); void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, u16 *iv16); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a3564..391e08fa054b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -54,6 +54,11 @@ static bool modparam_nohwcrypt = false; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ + return modparam_nohwcrypt; +} + static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) { unsigned int i; @@ -965,76 +970,14 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) /* * Device probe functions. */ -static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static void rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) { - /* - * Read EEPROM into buffer - */ if (rt2x00_is_soc(rt2x00dev)) rt2800pci_read_eeprom_soc(rt2x00dev); else if (rt2800pci_efuse_detect(rt2x00dev)) rt2800pci_read_eeprom_efuse(rt2x00dev); else rt2800pci_read_eeprom_pci(rt2x00dev); - - return rt2800_validate_eeprom(rt2x00dev); -} - -static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt2800pci_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2800_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt2800_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device has multiple filters for control frames - * and has a separate filter for PS Poll frames. - */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); - - /* - * This device has a pre tbtt interrupt and thus fetches - * a new beacon directly prior to transmission. - */ - __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); - - /* - * This device requires firmware. - */ - if (!rt2x00_is_soc(rt2x00dev)) - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); - if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; } static const struct ieee80211_ops rt2800pci_mac80211_ops = { @@ -1072,6 +1015,8 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { .register_multiread = rt2x00pci_register_multiread, .register_multiwrite = rt2x00pci_register_multiwrite, .regbusy_read = rt2x00pci_regbusy_read, + .read_eeprom = rt2800pci_read_eeprom, + .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, .drv_write_firmware = rt2800pci_write_firmware, .drv_init_registers = rt2800pci_init_registers, .drv_get_txwi = rt2800pci_get_txwi, @@ -1084,7 +1029,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .tbtt_tasklet = rt2800pci_tbtt_tasklet, .rxdone_tasklet = rt2800pci_rxdone_tasklet, .autowake_tasklet = rt2800pci_autowake_tasklet, - .probe_hw = rt2800pci_probe_hw, + .probe_hw = rt2800_probe_hw, .get_firmware_name = rt2800pci_get_firmware_name, .check_firmware = rt2800_check_firmware, .load_firmware = rt2800_load_firmware, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e25..603b65d6f28b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -49,6 +49,11 @@ static bool modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ + return modparam_nohwcrypt; +} + /* * Queue handlers. */ @@ -667,8 +672,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * FIXME: we need to check for rx_pkt_len validity + * Check for rx_pkt_len validity. Return if invalid, leaving + * rxdesc->size zeroed out by the upper level. */ + if (unlikely(rx_pkt_len == 0 || + rx_pkt_len > entry->queue->data_size)) { + ERROR(entry->queue->rt2x00dev, + "Bad frame size %d, forcing to 0\n", rx_pkt_len); + return; + } + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* @@ -722,64 +735,27 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, /* * Device probe functions. */ -static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static void rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev) { if (rt2800_efuse_detect(rt2x00dev)) rt2800_read_eeprom_efuse(rt2x00dev); else rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); - - return rt2800_validate_eeprom(rt2x00dev); } static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - /* - * Allocate eeprom data. - */ - retval = rt2800usb_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2800_init_eeprom(rt2x00dev); + retval = rt2800_probe_hw(rt2x00dev); if (retval) return retval; /* - * Initialize hw specifications. + * Set txstatus timer function. */ - retval = rt2800_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device has multiple filters for control frames - * and has a separate filter for PS Poll frames. - */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); - - /* - * This device requires firmware. - */ - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); - if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); - - rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout, - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout; /* * Overwrite TX done handler @@ -825,6 +801,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { .register_multiread = rt2x00usb_register_multiread, .register_multiwrite = rt2x00usb_register_multiwrite, .regbusy_read = rt2x00usb_regbusy_read, + .read_eeprom = rt2800usb_read_eeprom, + .hwcrypt_disabled = rt2800usb_hwcrypt_disabled, .drv_write_firmware = rt2800usb_write_firmware, .drv_init_registers = rt2800usb_init_registers, .drv_get_txwi = rt2800usb_get_txwi, @@ -1157,6 +1135,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1222,7 +1202,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index f991e8bedc70..49375c86c334 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -188,6 +188,7 @@ struct rt2x00_chip { #define RT3071 0x3071 #define RT3090 0x3090 /* 2.4GHz PCIe */ #define RT3290 0x3290 +#define RT3352 0x3352 /* WSOC */ #define RT3390 0x3390 #define RT3572 0x3572 #define RT3593 0x3593 diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a59048ffa092..10cf67267775 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9a..2673e058caaf 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -243,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT5); + return rt2x00_get_field32(reg, MAC_CSR13_VAL5); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -715,11 +715,11 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - rt2x00_set_field32(®, MAC_CSR13_BIT4, p1); - rt2x00_set_field32(®, MAC_CSR13_BIT12, 0); + rt2x00_set_field32(®, MAC_CSR13_DIR4, 0); + rt2x00_set_field32(®, MAC_CSR13_VAL4, p1); - rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2); - rt2x00_set_field32(®, MAC_CSR13_BIT11, 0); + rt2x00_set_field32(®, MAC_CSR13_DIR3, 0); + rt2x00_set_field32(®, MAC_CSR13_VAL3, !p2); rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); } @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2850,6 +2851,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_DIR5, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + + /* * Initialize hw specifications. */ retval = rt61pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0e..9bc6b6044e34 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -357,21 +357,22 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR13: GPIO. + * MAC_CSR13_VALx: GPIO value + * MAC_CSR13_DIRx: GPIO direction: 0 = output; 1 = input */ #define MAC_CSR13 0x3034 -#define MAC_CSR13_BIT0 FIELD32(0x00000001) -#define MAC_CSR13_BIT1 FIELD32(0x00000002) -#define MAC_CSR13_BIT2 FIELD32(0x00000004) -#define MAC_CSR13_BIT3 FIELD32(0x00000008) -#define MAC_CSR13_BIT4 FIELD32(0x00000010) -#define MAC_CSR13_BIT5 FIELD32(0x00000020) -#define MAC_CSR13_BIT6 FIELD32(0x00000040) -#define MAC_CSR13_BIT7 FIELD32(0x00000080) -#define MAC_CSR13_BIT8 FIELD32(0x00000100) -#define MAC_CSR13_BIT9 FIELD32(0x00000200) -#define MAC_CSR13_BIT10 FIELD32(0x00000400) -#define MAC_CSR13_BIT11 FIELD32(0x00000800) -#define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_VAL0 FIELD32(0x00000001) +#define MAC_CSR13_VAL1 FIELD32(0x00000002) +#define MAC_CSR13_VAL2 FIELD32(0x00000004) +#define MAC_CSR13_VAL3 FIELD32(0x00000008) +#define MAC_CSR13_VAL4 FIELD32(0x00000010) +#define MAC_CSR13_VAL5 FIELD32(0x00000020) +#define MAC_CSR13_DIR0 FIELD32(0x00000100) +#define MAC_CSR13_DIR1 FIELD32(0x00000200) +#define MAC_CSR13_DIR2 FIELD32(0x00000400) +#define MAC_CSR13_DIR3 FIELD32(0x00000800) +#define MAC_CSR13_DIR4 FIELD32(0x00001000) +#define MAC_CSR13_DIR5 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859d..cfa9f37cccc2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -189,7 +189,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT7); + return rt2x00_get_field32(reg, MAC_CSR13_VAL7); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_DIR7, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + + /* * Initialize hw specifications. */ retval = rt73usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d3..7577e0ba3877 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -267,21 +267,26 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR13: GPIO. + * MAC_CSR13_VALx: GPIO value + * MAC_CSR13_DIRx: GPIO direction: 0 = input; 1 = output */ #define MAC_CSR13 0x3034 -#define MAC_CSR13_BIT0 FIELD32(0x00000001) -#define MAC_CSR13_BIT1 FIELD32(0x00000002) -#define MAC_CSR13_BIT2 FIELD32(0x00000004) -#define MAC_CSR13_BIT3 FIELD32(0x00000008) -#define MAC_CSR13_BIT4 FIELD32(0x00000010) -#define MAC_CSR13_BIT5 FIELD32(0x00000020) -#define MAC_CSR13_BIT6 FIELD32(0x00000040) -#define MAC_CSR13_BIT7 FIELD32(0x00000080) -#define MAC_CSR13_BIT8 FIELD32(0x00000100) -#define MAC_CSR13_BIT9 FIELD32(0x00000200) -#define MAC_CSR13_BIT10 FIELD32(0x00000400) -#define MAC_CSR13_BIT11 FIELD32(0x00000800) -#define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_VAL0 FIELD32(0x00000001) +#define MAC_CSR13_VAL1 FIELD32(0x00000002) +#define MAC_CSR13_VAL2 FIELD32(0x00000004) +#define MAC_CSR13_VAL3 FIELD32(0x00000008) +#define MAC_CSR13_VAL4 FIELD32(0x00000010) +#define MAC_CSR13_VAL5 FIELD32(0x00000020) +#define MAC_CSR13_VAL6 FIELD32(0x00000040) +#define MAC_CSR13_VAL7 FIELD32(0x00000080) +#define MAC_CSR13_DIR0 FIELD32(0x00000100) +#define MAC_CSR13_DIR1 FIELD32(0x00000200) +#define MAC_CSR13_DIR2 FIELD32(0x00000400) +#define MAC_CSR13_DIR3 FIELD32(0x00000800) +#define MAC_CSR13_DIR4 FIELD32(0x00001000) +#define MAC_CSR13_DIR5 FIELD32(0x00002000) +#define MAC_CSR13_DIR6 FIELD32(0x00004000) +#define MAC_CSR13_DIR7 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. |