summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2018-12-04 10:47:33 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2018-12-04 10:47:33 +0000
commit0cf530cb1e36e672c7a8cbef6f1b9b834e20c675 (patch)
tree93e1c9f8eb46d05134a4cbe18055e1a5335d0f99 /sys/dev
parent2975b01a5b89f23dc156323c95b38cbbbc45ffc0 (diff)
Add support for RTL8192EU adapters, partly taken from netbsd.
These show up with a variety of vendor/product ids, but the driver will only match those we've tested so far. help and testing from kevlo@ ok stsp@ kevlo@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/r92creg.h424
-rw-r--r--sys/dev/ic/rtwn.c575
-rw-r--r--sys/dev/ic/rtwnvar.h4
-rw-r--r--sys/dev/usb/if_urtwn.c397
4 files changed, 1207 insertions, 193 deletions
diff --git a/sys/dev/ic/r92creg.h b/sys/dev/ic/r92creg.h
index 68bc56b834a..6adabc733ef 100644
--- a/sys/dev/ic/r92creg.h
+++ b/sys/dev/ic/r92creg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: r92creg.h,v 1.21 2018/10/01 22:36:08 jmatthew Exp $ */
+/* $OpenBSD: r92creg.h,v 1.22 2018/12/04 10:47:32 jmatthew Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -31,6 +31,7 @@
#define R92C_SYS_CLKR 0x008
#define R92C_AFE_MISC 0x010
#define R92C_SPS0_CTRL 0x011
+#define R92C_SYS_SWR_CTRL2 0x014
#define R92C_SPS_OCP_CFG 0x018
#define R92C_RSV_CTRL 0x01c
#define R92C_RF_CTRL 0x01f
@@ -40,6 +41,7 @@
#define R92C_LPLDO_CTRL 0x023
#define R92C_AFE_XTAL_CTRL 0x024
#define R92C_AFE_PLL_CTRL 0x028
+#define R92C_AFE_CTRL3 0x02c
#define R92C_EFUSE_CTRL 0x030
#define R92C_EFUSE_TEST 0x034
#define R92C_PWR_DATA 0x038
@@ -60,6 +62,7 @@
#define R92C_HSISR 0x05c
#define R92C_AFE_XTAL_CTRL_EXT 0x078
#define R88E_XCK_OUT_CTRL 0x07c
+#define R92E_LDO_SWR_CTRL 0x07c
#define R92C_MCUFWDL 0x080
#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2)
#define R88E_HIMR 0x0b0
@@ -117,11 +120,14 @@
#define R92C_TXDMA_OFFSET_CHK 0x20c
#define R92C_TXDMA_STATUS 0x210
#define R92C_RQPN_NPQ 0x214
+#define R92E_AUTO_LLT 0x224
+#define R92E_DWBCN1_CTRL 0x228
/* Rx DMA Configuration. */
#define R92C_RXDMA_AGG_PG_TH 0x280
#define R92C_RXPKT_NUM 0x284
#define R88E_RXDMA_CTRL 0x286
#define R92C_RXDMA_STATUS 0x288
+#define R92E_RXDMA_PRO 0x290
#define R92C_PCIE_CTRL_REG 0x300
#define R92C_INT_MIG 0x304
@@ -168,8 +174,11 @@
#define R92C_FAST_EDCA_CTRL 0x460
#define R92C_RD_RESP_PKT_TH 0x463
#define R92C_INIRTS_RATE_SEL 0x480
+#define R92E_DATA_SC 0x483
#define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid))
+#define R92C_QUEUE_CTRL 0x4c6
#define R92C_MAX_AGGR_NUM 0x4ca
+#define R92C_BAR_MODE_CTRL 0x4cc
#define R88E_TX_RPT_CTRL 0x4ec
#define R88E_TX_RPT_TIME 0x4f0
/* EDCA Configuration. */
@@ -229,6 +238,7 @@
#define R92C_RESP_SIFS_CCK 0x63c
#define R92C_RESP_SIFS_OFDM 0x63e
#define R92C_ACKTO 0x640
+#define R92C_NAV_UPPER 0x652
#define R92C_WMAC_TRXPTCL_CTL 0x668
#define R92C_CAMCMD 0x670
#define R92C_CAMWRITE 0x674
@@ -239,6 +249,9 @@
#define R92C_RXFLTMAP1 0x6a2
#define R92C_RXFLTMAP2 0x6a4
+#define R92C_CONFIG_ANT_A 0xb68
+#define R92C_CONFIG_ANT_B 0xb6c
+
/* Bits for R92C_SYS_ISO_CTRL. */
#define R92C_SYS_ISO_CTRL_MD2PP 0x0001
#define R92C_SYS_ISO_CTRL_UA2USB 0x0002
@@ -321,6 +334,7 @@
#define R92C_RSV_CTRL_R_DIS_PRST_0 0x20
#define R92C_RSV_CTRL_R_DIS_PRST_1 0x40
#define R92C_RSV_CTRL_LOCK_ALL_EN 0x80
+#define R88E_RSV_CTRL_MIO_EN 0x0100
/* Bits for R92C_RF_CTRL. */
#define R92C_RF_CTRL_EN 0x01
@@ -355,6 +369,9 @@
/* Bits for R92C_LEDCFG0. */
#define R92C_LEDCFG0_DIS 0x08
+/* Bits for R92C_LEDCFG1. */
+#define R92E_LEDSON 0x60
+
/* Bits for R92C_LEDCFG2. */
#define R92C_LEDCFG2_EN 0x60
#define R92C_LEDCFG2_DIS 0x68
@@ -440,6 +457,7 @@
#define R92C_SYS_CFG_PAD_HWPD_IDN 0x00400000
#define R92C_SYS_CFG_TRP_VAUX_EN 0x00800000
#define R92C_SYS_CFG_TRP_BT_EN 0x01000000
+#define R92E_SYS_CFG_SPSLDO_SEL 0x01000000
#define R92C_SYS_CFG_BD_PKG_SEL 0x02000000
#define R92C_SYS_CFG_BD_HCI_SEL 0x04000000
#define R92C_SYS_CFG_TYPE_92C 0x08000000
@@ -511,6 +529,7 @@
#define R92C_LLT_INIT_OP_S 30
#define R92C_LLT_INIT_OP_NO_ACTIVE 0
#define R92C_LLT_INIT_OP_WRITE 1
+#define R92C_LLT_INIT_OP_READ 2
/* Bits for R92C_RQPN. */
#define R92C_RQPN_HPQ_M 0x000000ff
@@ -525,6 +544,9 @@
#define R92C_TDECTRL_BLK_DESC_NUM_M 0x000000f0
#define R92C_TDECTRL_BLK_DESC_NUM_S 4
+/* Bits for R92E_AUTO_LLT. */
+#define R92E_AUTO_LLT_EN 0x00010000
+
/* Bits for R92C_FWHW_TXQ_CTRL. */
#define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80
@@ -648,6 +670,12 @@
/* Bits for R92C_WMAC_TRXPTCL_CTL. */
#define R92C_WMAC_TRXPTCL_CTL_SHORT 0x00020000
+#define R92C_WMAC_TRXPTCL_CTL_BW_20 0
+#define R92C_WMAC_TRXPTCL_CTL_BW_40 0x00000080
+#define R92C_WMAC_TRXPTCL_CTL_BW_80 0x00000100
+#define R92C_WMAC_TRXPTCL_CTL_BW_MASK \
+ (R92C_WMAC_TRXPTCL_CTL_BW_40 | \
+ R92C_WMAC_TRXPTCL_CTL_BW_80)
/* Bits for R92C_CAMCMD. */
#define R92C_CAMCMD_ADDR_M 0x0000ffff
@@ -731,6 +759,7 @@
*/
#define R92C_FPGA0_RFMOD 0x800
#define R92C_FPGA0_TXINFO 0x804
+#define R92C_FPGA0_POWER_SAVE 0x818
#define R92C_HSSI_PARAM1(chain) (0x820 + (chain) * 8)
#define R92C_HSSI_PARAM2(chain) (0x824 + (chain) * 8)
#define R92C_TXAGC_RATE18_06(i) (((i) == 0) ? 0xe00 : 0x830)
@@ -763,8 +792,33 @@
#define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8)
#define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8)
#define R92C_OFDM0_RXIQEXTANTA 0xca0
+#define R92C_OFDM0_TX_PSDO_NOISE_WEIGHT 0xce4
#define R92C_OFDM1_LSTF 0xd00
+#define R92C_FPGA0_IQK 0xe28
+#define R92C_TX_IQK_TONE_A 0xe30
+#define R92C_RX_IQK_TONE_A 0xe34
+#define R92C_TX_IQK_PI_A 0xe38
+#define R92C_RX_IQK_PI_A 0xe3c
+#define R92C_TX_IQK 0xe40
+#define R92C_RX_IQK 0xe44
+#define R92C_IQK_AGC_PTS 0xe48
+#define R92C_IQK_AGC_RSP 0xe4c
+#define R92C_TX_IQK_TONE_B 0xe50
+#define R92C_RX_IQK_TONE_B 0xe54
+#define R92C_TX_IQK_PI_B 0xe58
+#define R92C_RX_IQK_PI_B 0xe5c
+#define R92C_IQK_AGC_CONT 0xe60
+
+#define R92E_RX_WAIT_CCA 0xe70
+
+#define R92C_TX_POWER_BEFORE_IQK_A 0xe94
+#define R92C_TX_POWER_AFTER_IQK_A 0xe9c
+#define R92C_RX_POWER_BEFORE_IQK_A 0xea0
+#define R92C_RX_POWER_BEFORE_IQK_A_2 0xea4
+#define R92C_RX_POWER_AFTER_IQK_A 0xea8
+#define R92C_RX_POWER_AFTER_IQK_A_2 0xeac
+
/* Bits for R92C_FPGA[01]_RFMOD. */
#define R92C_RFMOD_40MHZ 0x00000001
#define R92C_RFMOD_JAPAN 0x00000002
@@ -915,7 +969,6 @@
#define R92C_USB_EP_LQ_M 0x0f00
#define R92C_USB_EP_LQ_S 8
-
/*
* Firmware base address.
*/
@@ -953,6 +1006,7 @@
#define R92C_RF_SYN_G(i) (0x25 + (i))
#define R92C_RF_RCK_OS 0x30
#define R92C_RF_TXPA_G(i) (0x31 + (i))
+#define R92E_RF_T_METER 0x42
/* Bits for R92C_RF_AC. */
#define R92C_RF_AC_MODE_M 0x70000
@@ -997,6 +1051,10 @@
#define R92C_RAID_11G 5 /* "pure" 11g */
#define R92C_RAID_11B 6
+#define R92E_RAID_11BG 6
+#define R92E_RAID_11G 7 /* "pure" 11g */
+#define R92E_RAID_11B 8
+
/* Macros to access unaligned little-endian memory. */
#define LE_READ_2(x) ((x)[0] | (x)[1] << 8)
@@ -1076,6 +1134,50 @@ struct r92c_fw_cmd_macid_cfg {
#define R92C_MACID_BSS 0
#define R92C_MACID_BC 4 /* Broadcast. */
#define R92C_MACID_VALID 0x80
+#define R92C_MACID_SHORTGI 0x20
+} __packed;
+
+/* Structure for R92C_CMD_SET_PWRMODE. */
+struct r92c_fw_cmd_setpwrmode {
+ uint8_t mode;
+ uint8_t smartps;
+ uint8_t bcn_time; /* 100ms increments */
+} __packed;
+
+#define R92E_CMD_KEEP_ALIVE 0x03
+#define R92E_CMD_SET_PWRMODE 0x20
+#define R92E_CMD_RSSI_REPORT 0x42
+
+/* Structure for R92E_CMD_KEEP_ALIVE. */
+struct r92e_fw_cmd_keepalive {
+ uint8_t mode;
+ uint8_t period;
+} __packed;
+
+/* Structure for R92E_CMD_SET_PWRMODE. */
+struct r92e_fw_cmd_setpwrmode {
+ uint8_t mode;
+#define FWMODE_ACTIVE 0
+#define FWMODE_LOW_POWER 1
+#define FWMODE_WMMPS 2
+ uint8_t smartps;
+#define SRTPS_LOW_POWER 0
+#define SRTPS_POLL 0x10
+#define SRTPS_WMMPS 0x20
+ uint8_t awake_int; /* 100ms increments. */
+ uint8_t all_queue_apsd;
+ uint8_t pwr_state;
+#define PS_PFOFF 0x00
+#define PS_RFON 0x04
+#define PS_ALLON 0x0c
+} __packed;
+
+/* Structure for R92E_CMD_RSSI_REPORT. */
+struct r92e_fw_cmd_rssi {
+ uint8_t macid;
+ uint8_t reserved;
+ uint8_t pwdb;
+ uint8_t reserved2;
} __packed;
/*
@@ -1125,6 +1227,57 @@ struct r92c_rom {
uint8_t curstomer_id;
} __packed;
+struct r92e_tx_pwr {
+ uint8_t cck_tx_pwr[6];
+ uint8_t ht40_tx_pwr[5];
+ uint8_t ht20_ofdm_tx_pwr_diff;
+#define R92E_ROM_TXPWR_HT20_DIFF_M 0xf0
+#define R92E_ROM_TXPWR_HT20_DIFF_S 4
+#define R92E_ROM_TXPWR_OFDM_DIFF_M 0x0f
+#define R92E_ROM_TXPWR_OFDM_DIFF_S 0
+ uint16_t pwr_diff[3];
+ uint8_t reserved[24];
+} __packed;
+
+struct r92e_rom {
+ uint16_t id;
+ uint8_t reserved[14];
+ struct r92e_tx_pwr txpwr_a;
+ struct r92e_tx_pwr txpwr_b;
+ uint8_t reserved2[84];
+ uint8_t channel_plan;
+ uint8_t xtal_k;
+ uint8_t thermal_meter;
+ uint8_t iqk_lck;
+ uint8_t pa_type;
+ uint8_t lna_type_2g;
+ uint8_t reserved3;
+ uint8_t lna_type_5g;
+ uint8_t reserved4;
+ uint8_t rf_board_opt;
+ uint8_t rf_feature_opt;
+ uint8_t rf_bt_opt;
+ uint8_t eeprom_version;
+ uint8_t eeprom_customer_id;
+ uint8_t reserved5[3];
+ uint8_t rf_antenna_option;
+ uint8_t reserved6[6];
+ uint16_t vid;
+ uint16_t pid;
+ uint8_t usb_optional_function;
+ uint8_t reserved9[2];
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ uint8_t reserved10[2];
+ uint8_t vendor[7];
+ uint8_t reserved11[2];
+ uint8_t device_name[11];
+ uint8_t reserved12[2];
+ uint8_t serial[11];
+ uint8_t reserved13[48];
+ uint8_t unknown[13];
+ uint8_t reserved14[195];
+} __packed;
+
struct r88e_tx_pwr {
uint8_t cck_tx_pwr[6];
uint8_t ht40_tx_pwr[5];
@@ -1342,6 +1495,7 @@ struct r92c_rx_desc_usb {
#define R92C_RXDW2_PKTCNT_M 0x00ff0000
#define R92C_RXDW2_PKTCNT_S 16
+#define R92E_RXDW2_RPT_C2H 0x10000000
#define R92C_RXDW3_RATE_M 0x0000003f
#define R92C_RXDW3_RATE_S 0
@@ -1387,6 +1541,21 @@ struct r92c_tx_desc_usb {
uint16_t pad;
} __packed __attribute__((aligned(4)));
+struct r92e_tx_desc_usb {
+ uint32_t txdw0;
+ uint32_t txdw1;
+ uint32_t txdw2;
+ uint32_t txdw3;
+ uint32_t txdw4;
+ uint32_t txdw5;
+ uint32_t txdw6;
+ uint16_t txdsum;
+ uint16_t pad;
+ uint32_t txdw7;
+ uint16_t txdseq2;
+ uint16_t txdw8;
+} __packed __attribute__((aligned(4)));
+
#define R92C_TXDW0_PKTLEN_M 0x0000ffff
#define R92C_TXDW0_PKTLEN_S 0
#define R92C_TXDW0_OFFSET_M 0x00ff0000
@@ -1400,6 +1569,8 @@ struct r92c_tx_desc_usb {
#define R92C_TXDW1_MACID_S 0
#define R88E_TXDW1_MACID_M 0x0000003f
#define R88E_TXDW1_MACID_S 0
+#define R92E_TXDW1_MACID_M 0x0000007f
+#define R92E_TXDW1_MACID_S 0
#define R92C_TXDW1_AGGEN 0x00000020
#define R92C_TXDW1_AGGBK 0x00000040
#define R92C_TXDW1_QSEL_M 0x00001f00
@@ -1425,6 +1596,7 @@ struct r92c_tx_desc_usb {
#define R88E_TXDW2_AGGBK 0x00010000
#define R92C_TXDW2_CCX_RPT 0x00080000
+#define R92E_TXDW3_DRVRATE 0x1000
#define R23A_TXDW3_TXRPTEN 0x4000
#define R92C_TXDW3_HWSEQEN 0x8000
@@ -1444,6 +1616,18 @@ struct r92c_tx_desc_usb {
#define R92C_TXDW4_40MHZ 0x02000000
#define R92C_TXDW4_RTS_SHORT 0x04000000
+#define R92E_TXDW4_DATARATE_M 0x0000007f
+#define R92E_TXDW4_DATARATE_S 0
+#define R92E_TXDW4_DATARATEFB_M 0x00001f00
+#define R92E_TXDW4_DATARATEFB_S 8
+#define R92E_TXDW4_RTSRATEFB_M 0x0001e000
+#define R92E_TXDW4_RTSRATEFB_S 13
+#define R92E_TXDW4_RETRYLMT_ENA 0x00020000
+#define R92E_TXDW4_RETRYLMT_M 0x00fc0000
+#define R92E_TXDW4_RETRYLMT_S 18
+#define R92E_TXDW4_RTSRATE_M 0x1f000000
+#define R92E_TXDW4_RTSRATE_S 24
+
#define R92C_TXDW5_DATARATE_M 0x0000003f
#define R92C_TXDW5_DATARATE_S 0
#define R92C_TXDW5_SGI 0x00000040
@@ -1457,6 +1641,9 @@ struct r92c_tx_desc_usb {
#define R92C_TXDW5_AGGNUM_M 0xff000000
#define R92C_TXDW5_AGGNUM_S 24
+#define R92E_TXDSEQ2_HWSEQ_S 11
+#define R92E_TXDSEQ2_HWSEQ_M 0x0000ffff
+
/*
* C2H event structure.
*/
@@ -1522,6 +1709,26 @@ struct r92c_c2h_tx_rpt {
#define R92C_RPTB7_INT_CCX 0x80
} __packed;
+struct r92e_c2h_tx_rpt {
+ uint8_t rptb0;
+#define R92E_RPTB0_QSEL_M 0x1f
+#define R92E_RPTB0_QSEL_S 0
+#define R92E_RPTB0_BC 0x20
+#define R92E_RPTB0_LIFE_EXPIRE 0x40
+#define R92E_RPTB0_RETRY_OVER 0x80
+
+ uint8_t macid;
+
+ uint8_t rptb2;
+#define R92E_RPTB2_RETRY_CNT_M 0x3f
+#define R92E_RPTB2_RETRY_CNT_S 0
+
+ uint8_t queue_time_low;
+ uint8_t queue_time_high;
+ uint8_t final_rate;
+ uint16_t reserved;
+} __packed;
+
/*
* MAC initialization values.
*/
@@ -1597,6 +1804,33 @@ static const struct {
{ 0x63f, 0x0e }, { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 },
{ 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 },
{ 0x70a, 0x65 }, { 0x70b, 0x87 }
+}, rtl8192eu_mac[]={
+ { 0x011, 0xeb }, { 0x012, 0x07 }, { 0x014, 0x75 }, { 0x303, 0xa7 },
+ { 0x421, 0x0f }, { 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 },
+ { 0x431, 0x00 }, { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 },
+ { 0x435, 0x05 }, { 0x436, 0x07 }, { 0x437, 0x08 }, { 0x43c, 0x04 },
+ { 0x43d, 0x05 }, { 0x43e, 0x07 }, { 0x43f, 0x08 }, { 0x440, 0x5d },
+ { 0x441, 0x01 }, { 0x442, 0x00 }, { 0x444, 0x10 }, { 0x445, 0x00 },
+ { 0x446, 0x00 }, { 0x447, 0x00 }, { 0x448, 0x00 }, { 0x449, 0xf0 },
+ { 0x44a, 0x0f }, { 0x44b, 0x3e }, { 0x44c, 0x10 }, { 0x44d, 0x00 },
+ { 0x44e, 0x00 }, { 0x44f, 0x00 }, { 0x450, 0x00 }, { 0x451, 0xf0 },
+ { 0x452, 0x0f }, { 0x453, 0x00 }, { 0x456, 0x5e }, { 0x460, 0x66 },
+ { 0x461, 0x66 }, { 0x4c8, 0xff }, { 0x4c9, 0x08 }, { 0x4cc, 0xff },
+ { 0x4cd, 0xff }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 },
+ { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 },
+ { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 },
+ { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 },
+ { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a },
+ { 0x516, 0x0a }, { 0x525, 0x4f }, { 0x540, 0x12 }, { 0x541, 0x64 },
+ { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 },
+ { 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a },
+ { 0x620, 0xff }, { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff },
+ { 0x624, 0xff }, { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff },
+ { 0x638, 0x50 }, { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e },
+ { 0x63f, 0x0e }, { 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 },
+ { 0x652, 0x2b }, { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 },
+ { 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 },
+ { 0x70a, 0x65 }, { 0x70b, 0x87 }
};
/*
@@ -2454,6 +2688,79 @@ static const struct r92c_rf_prog rtl8188cu_rf_prog[] = {
};
/*
+ * RTL8192EE and RTL8192EU.
+ */
+static const uint8_t rtl8192e_rf_regs[] = {
+ 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f,
+ 0x42, 0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1,
+ 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0x1c, 0xdf,
+ 0xef, 0x51, 0x52, 0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+ 0x36, 0x18, 0x5a, 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0xfe, 0x18, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0x1e, 0x1f, 0x00
+};
+
+static const uint32_t rtl8192e_rf_vals[] = {
+ 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x0394c,
+ 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
+ 0x01552, 0x00000, 0xff9f1, 0x55418, 0x8cc00, 0x43083, 0x08166,
+ 0x0803e, 0x1c69f, 0x0407f, 0x90001, 0x40001, 0x00400, 0x00078,
+ 0xb3333, 0x33340, 0x00000, 0x05999, 0x09999, 0x02400, 0x00009,
+ 0x40c91, 0x99999, 0x000a3, 0x88820, 0x76c06, 0x00000, 0x80000,
+ 0x00000, 0x00180, 0x001a0, 0x69545, 0x7e45e, 0x00071, 0x51ff3,
+ 0x000a8, 0x001e2, 0x002a8, 0x01c24, 0x09c24, 0x11c24, 0x19c24,
+ 0x00c07, 0x48000, 0x739d0, 0x0add7, 0x09dd4, 0x08dd1, 0x07dce,
+ 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc, 0x0244f, 0x0144c, 0x00014,
+ 0x30159, 0x68180, 0x0014e, 0x49f80, 0x65540, 0x88000, 0x020a0,
+ 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080,
+ 0x8f780, 0x78730, 0x60fb0, 0x5ffa0, 0x40620, 0x37090, 0x20080,
+ 0x1f060, 0x0ffb0, 0x000a0, 0x00000, 0x0fc07, 0x00000, 0x00000,
+ 0x00000, 0x00000, 0x00001, 0x80000, 0x33e70
+};
+
+static const uint8_t rtl8192e_rf2_regs[] = {
+ 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f,
+ 0x42, 0x57, 0x58, 0x67, 0x7f, 0x81, 0x83, 0x1c, 0xdf, 0xef, 0x51,
+ 0x52, 0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x18,
+ 0x5a, 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b, 0x3b,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0x3b, 0x3b, 0x3b, 0xef, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x1f,
+ 0x00
+};
+
+static const uint32_t rtl8192e_rf2_vals[] = {
+ 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x0394c,
+ 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
+ 0x01552, 0x00082, 0x3f000, 0x00000, 0x00000, 0x00180, 0x001a0,
+ 0x69545, 0x7e42e, 0x00071, 0x51ff3, 0x000a8, 0x001e0, 0x002a8,
+ 0x01ca8, 0x09c24, 0x11c24, 0x19c24, 0x00c07, 0x48000, 0x739d0,
+ 0x0add7, 0x09dd4, 0x08dd1, 0x07dce, 0x06dcb, 0x05dc8, 0x04dc5,
+ 0x034cc, 0x0244f, 0x0144c, 0x00014, 0x30159, 0x68180, 0x000ce,
+ 0x49f80, 0x65540, 0x88000, 0x020a0, 0xf02b0, 0xef7b0, 0xd4fb0,
+ 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780, 0x78730, 0x60fb0,
+ 0x5ffa0, 0x40620, 0x37090, 0x20080, 0x1f060, 0x0ffb0, 0x000a0,
+ 0x10159, 0x00000, 0x00000, 0x00000, 0x00000, 0x00001, 0x80000,
+ 0x33e70
+};
+
+static const struct r92c_rf_prog rtl8192e_rf_prog[] = {
+ {
+ nitems(rtl8192e_rf_regs),
+ rtl8192e_rf_regs,
+ rtl8192e_rf_vals
+ },
+ {
+ nitems(rtl8192e_rf2_regs),
+ rtl8192e_rf2_regs,
+ rtl8192e_rf2_vals
+ }
+};
+
+/*
* RTL8188EU.
*/
static const uint8_t rtl8188eu_rf_regs[] = {
@@ -2494,6 +2801,119 @@ static const struct r92c_rf_prog rtl8188eu_rf_prog[] = {
};
/*
+ * RTL8192EE and RTL8192EU.
+ */
+static const uint16_t rtl8192e_bb_regs[] = {
+ 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, 0x820,
+ 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844,
+ 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868,
+ 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, 0x888, 0x88c,
+ 0x890, 0x894, 0x898, 0x900, 0x904, 0x908, 0x90c, 0x910, 0x914,
+ 0x918, 0x91c, 0x924, 0x928, 0x92c, 0x930, 0x934, 0x938, 0x93c,
+ 0x940, 0x944, 0x94c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14,
+ 0xa18, 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78,
+ 0xa7c, 0xa80, 0xb38, 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, 0xc14,
+ 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38,
+ 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c,
+ 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, 0xc80,
+ 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4,
+ 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, 0xcbc, 0xcc0, 0xcc4, 0xcc8,
+ 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, 0xce0, 0xce4, 0xce8, 0xcec,
+ 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, 0xd14, 0xd18, 0xd1c, 0xd2c,
+ 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50,
+ 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74,
+ 0xd78, 0xd80, 0xd84, 0xd88, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14,
+ 0xe18, 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44,
+ 0xe48, 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c,
+ 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0,
+ 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xee4, 0xee8, 0xf14, 0xf4c,
+ 0xf00
+};
+
+static const uint32_t rtl8192e_bb_vals[] = {
+ 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331,
+ 0x020c3d10, 0x02220385, 0x00000000, 0x01000100, 0x00390204,
+ 0x01000100, 0x00390204, 0x32323232, 0x30303030, 0x30303030,
+ 0x30303030, 0x00010000, 0x00010000, 0x28282828, 0x28282828,
+ 0x00000000, 0x00000000, 0x009a009a, 0x01000014, 0x66f60000,
+ 0x061f0000, 0x30303030, 0x30303030, 0x00000000, 0x55004200,
+ 0x08080808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000,
+ 0xcc0000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00000000,
+ 0x00000023, 0x00000000, 0x81121313, 0x806c0001, 0x00000001,
+ 0x00000000, 0x00010000, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000008, 0x00d0c7c8, 0x81ff800c, 0x8c838300,
+ 0x2e68120f, 0x95009b78, 0x1114d028, 0x00881117, 0x89140f00,
+ 0x1a1b0000, 0x090e1317, 0x00000204, 0x00d30000, 0x101fff80,
+ 0x00000007, 0x00000900, 0x225b0606, 0x218075b1, 0x00000000,
+ 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000,
+ 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994,
+ 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
+ 0x00340020, 0x0080801f, 0x00000020, 0x00248492, 0x00000000,
+ 0x7112848b, 0x47c00bff, 0x00000036, 0x00000600, 0x02013169,
+ 0x0000001f, 0x00b91612, 0x40000100, 0x21f60000, 0x40000100,
+ 0xa0e40000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f,
+ 0x00000000, 0x000300a0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427,
+ 0x00766932, 0x00222222, 0x00040000, 0x77644302, 0x2f97d40c,
+ 0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333,
+ 0x3333bc43, 0x7a8f5b6b, 0x0000007f, 0xcc979975, 0x00000000,
+ 0x80608000, 0x00000000, 0x00127353, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000282,
+ 0x30032064, 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16,
+ 0x1812362e, 0x322c2220, 0x000e3c24, 0x01081008, 0x00000800,
+ 0xf0b50000, 0x30303030, 0x30303030, 0x03903030, 0x30303030,
+ 0x30303030, 0x30303030, 0x30303030, 0x00000000, 0x1000dc1f,
+ 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800,
+ 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102,
+ 0x28160d05, 0x00000008, 0x0fc05656, 0x03c09696, 0x03c09696,
+ 0x0c005656, 0x0c005656, 0x0c005656, 0x0c005656, 0x03c09696,
+ 0x0c005656, 0x03c09696, 0x03c09696, 0x03c09696, 0x03c09696,
+ 0x0000d6d6, 0x0000d6d6, 0x0fc01616, 0xb0000c1c, 0x00000001,
+ 0x00000003, 0x00000000, 0x00000300
+};
+
+static const uint32_t rtl8192eu_agc_vals[] = {
+ 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001,
+ 0xfb050001, 0xfb060001, 0xfa070001, 0xf9080001, 0xf8090001,
+ 0xf70a0001, 0xf60b0001, 0xf50c0001, 0xf40d0001, 0xf30e0001,
+ 0xf20f0001, 0xf1100001, 0xf0110001, 0xef120001, 0xee130001,
+ 0xed140001, 0xec150001, 0xeb160001, 0xea170001, 0xcd180001,
+ 0xcc190001, 0xcb1a0001, 0xca1b0001, 0xc91c0001, 0xc81d0001,
+ 0x071e0001, 0x061f0001, 0x05200001, 0x04210001, 0x03220001,
+ 0xaa230001, 0xa9240001, 0xa8250001, 0xa7260001, 0xa6270001,
+ 0x85280001, 0x84290001, 0x832a0001, 0x252b0001, 0x242c0001,
+ 0x232d0001, 0x222e0001, 0x672f0001, 0x66300001, 0x65310001,
+ 0x64320001, 0x63330001, 0x62340001, 0x61350001, 0x45360001,
+ 0x44370001, 0x43380001, 0x42390001, 0x413a0001, 0x403b0001,
+ 0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001,
+ 0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001,
+ 0xfb460001, 0xfa470001, 0xf9480001, 0xf8490001, 0xf74a0001,
+ 0xf64b0001, 0xf54c0001, 0xf44d0001, 0xf34e0001, 0xf24f0001,
+ 0xf1500001, 0xf0510001, 0xef520001, 0xee530001, 0xed540001,
+ 0xec550001, 0xeb560001, 0xea570001, 0xe9580001, 0xe8590001,
+ 0xe75a0001, 0xe65b0001, 0xe55c0001, 0xe45d0001, 0xe35e0001,
+ 0xe25f0001, 0xe1600001, 0x8a610001, 0x89620001, 0x88630001,
+ 0x87640001, 0x86650001, 0x85660001, 0x84670001, 0x83680001,
+ 0x82690001, 0x6b6a0001, 0x6a6b0001, 0x696c0001, 0x686d0001,
+ 0x676e0001, 0x666f0001, 0x65700001, 0x64710001, 0x63720001,
+ 0x62730001, 0x61740001, 0x49750001, 0x48760001, 0x47770001,
+ 0x46780001, 0x45790001, 0x447a0001, 0x437b0001, 0x427c0001,
+ 0x417d0001, 0x407e0001, 0x407f0001
+};
+
+static const struct r92c_bb_prog rtl8192eu_bb_prog = {
+ nitems(rtl8192e_bb_regs),
+ rtl8192e_bb_regs,
+ rtl8192e_bb_vals,
+ nitems(rtl8192eu_agc_vals),
+ rtl8192eu_agc_vals
+};
+
+
+/*
* RTL8188RU.
*/
static const uint32_t rtl8188ru_rf_vals[] = {
diff --git a/sys/dev/ic/rtwn.c b/sys/dev/ic/rtwn.c
index 59e2f55a564..ad1fa0b9884 100644
--- a/sys/dev/ic/rtwn.c
+++ b/sys/dev/ic/rtwn.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: rtwn.c,v 1.41 2018/10/04 01:14:30 kevlo Exp $ */
+/* $OpenBSD: rtwn.c,v 1.42 2018/12/04 10:47:32 jmatthew Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -98,7 +99,13 @@ struct rtwn_iq_cal_regs {
uint32_t gpio_muxcfg;
uint32_t ofdm0_trxpathena;
uint32_t ofdm0_trmuxpar;
+ uint32_t fpga0_rfifacesw0;
uint32_t fpga0_rfifacesw1;
+ uint32_t fpga0_rfifaceoe0;
+ uint32_t fpga0_rfifaceoe1;
+ uint32_t config_ant_a;
+ uint32_t config_ant_b;
+ uint32_t cck0_afesetting;
};
void rtwn_write_1(struct rtwn_softc *, uint16_t, uint8_t);
@@ -117,6 +124,7 @@ void rtwn_efuse_switch_power(struct rtwn_softc *);
int rtwn_read_chipid(struct rtwn_softc *);
void rtwn_read_rom(struct rtwn_softc *);
void rtwn_r92c_read_rom(struct rtwn_softc *);
+void rtwn_r92e_read_rom(struct rtwn_softc *);
void rtwn_r88e_read_rom(struct rtwn_softc *);
void rtwn_r23a_read_rom(struct rtwn_softc *);
int rtwn_media_change(struct ifnet *);
@@ -151,6 +159,9 @@ void rtwn_get_txpower(struct rtwn_softc *sc, int,
void rtwn_r92c_get_txpower(struct rtwn_softc *, int,
struct ieee80211_channel *, struct ieee80211_channel *,
uint16_t[]);
+void rtwn_r92e_get_txpower(struct rtwn_softc *, int,
+ struct ieee80211_channel *,
+ struct ieee80211_channel *, uint16_t[]);
void rtwn_r88e_get_txpower(struct rtwn_softc *, int,
struct ieee80211_channel *,
struct ieee80211_channel *, uint16_t[]);
@@ -205,6 +216,9 @@ rtwn_attach(struct device *pdev, struct rtwn_softc *sc)
if (sc->chip & RTWN_CHIP_92C) {
sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2;
sc->nrxchains = 2;
+ } else if (sc->chip & RTWN_CHIP_92E) {
+ sc->ntxchains = 2;
+ sc->nrxchains = 2;
} else {
sc->ntxchains = 1;
sc->nrxchains = 1;
@@ -226,6 +240,7 @@ rtwn_attach(struct device *pdev, struct rtwn_softc *sc)
printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
sc->sc_pdev->dv_xname,
(sc->chip & RTWN_CHIP_92C) ? "8192CU" :
+ (sc->chip & RTWN_CHIP_92E) ? "8192EU" :
(sc->chip & RTWN_CHIP_88E) ? "8188EU" :
(sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" :
(sc->board_type == R92C_BOARD_TYPE_MINICARD) ?
@@ -386,7 +401,7 @@ rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
for (ntries = 0; ntries < 100; ntries++) {
if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
break;
- DELAY(1);
+ DELAY(10);
}
if (ntries == 100) {
printf("%s: could not send firmware command %d\n",
@@ -401,7 +416,12 @@ rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
memcpy(cmd.msg, buf, len);
/* Write the first word last since that will trigger the FW. */
- rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *((uint8_t *)&cmd + 4));
+ if (sc->chip & RTWN_CHIP_92E)
+ rtwn_write_2(sc, R88E_HMEBOX_EXT(sc->fwcur),
+ *((uint8_t *)&cmd + 4));
+ else
+ rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur),
+ *((uint8_t *)&cmd + 4));
rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *((uint8_t *)&cmd + 0));
sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
@@ -419,13 +439,25 @@ rtwn_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
{
uint32_t param_addr;
- if (sc->chip & RTWN_CHIP_88E)
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_4(sc, R92C_FPGA0_POWER_SAVE,
+ rtwn_read_4(sc, R92C_FPGA0_POWER_SAVE) & ~0x20000);
+ }
+
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))
param_addr = SM(R88E_LSSI_PARAM_ADDR, addr);
else
param_addr = SM(R92C_LSSI_PARAM_ADDR, addr);
rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
param_addr | SM(R92C_LSSI_PARAM_DATA, val));
+
+ DELAY(1);
+
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_4(sc, R92C_FPGA0_POWER_SAVE,
+ rtwn_read_4(sc, R92C_FPGA0_POWER_SAVE) | 0x20000);
+ }
}
uint32_t
@@ -571,7 +603,7 @@ rtwn_read_chipid(struct rtwn_softc *sc)
{
uint32_t reg;
- if (sc->chip & RTWN_CHIP_88E) {
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)) {
sc->sc_flags |= RTWN_FLAG_EXT_HDR;
return (0);
}
@@ -615,6 +647,8 @@ rtwn_read_rom(struct rtwn_softc *sc)
{
if (sc->chip & RTWN_CHIP_88E)
rtwn_r88e_read_rom(sc);
+ else if (sc->chip & RTWN_CHIP_92E)
+ rtwn_r92e_read_rom(sc);
else if (sc->chip & RTWN_CHIP_23A)
rtwn_r23a_read_rom(sc);
else
@@ -645,6 +679,25 @@ rtwn_r92c_read_rom(struct rtwn_softc *sc)
}
void
+rtwn_r92e_read_rom(struct rtwn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct r92e_rom *rom = &sc->sc_r92e_rom;
+
+ /* Read full ROM image. */
+ rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r92e_rom,
+ sizeof(sc->sc_r92e_rom));
+
+ sc->crystal_cap = rom->xtal_k;
+ DPRINTF(("crystal cap=0x%x\n", sc->crystal_cap));
+
+ sc->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
+ DPRINTF(("regulatory type=%d\n", sc->regulatory));
+
+ IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
+}
+
+void
rtwn_r88e_read_rom(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -749,7 +802,7 @@ rtwn_ra_init(struct rtwn_softc *sc)
rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07f5);
}
- if (sc->chip & RTWN_CHIP_88E) {
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)) {
error = rtwn_r88e_ra_init(sc, mode, rates, maxrate,
basicrates, maxbasicrate);
/* We use AMRR with this chip. Start with the lowest rate. */
@@ -875,7 +928,17 @@ rtwn_set_led(struct rtwn_softc *sc, int led, int on)
reg |= R92C_LEDCFG2_EN;
rtwn_write_1(sc, R92C_LEDCFG2, reg);
} else if (sc->chip & RTWN_CHIP_USB) {
- if (sc->chip & RTWN_CHIP_88E) {
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_1(sc, 0x64, rtwn_read_1(sc, 0x64) & 0xfe);
+ reg = rtwn_read_1(sc, R92C_LEDCFG1) & R92E_LEDSON;
+ rtwn_write_1(sc, R92C_LEDCFG1, reg |
+ (R92C_LEDCFG0_DIS << 1));
+ if (on) {
+ reg = rtwn_read_1(sc, R92C_LEDCFG1) &
+ R92E_LEDSON;
+ rtwn_write_1(sc, R92C_LEDCFG1, reg);
+ }
+ } else if (sc->chip & RTWN_CHIP_88E) {
reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
rtwn_write_1(sc, R92C_LEDCFG2, reg | R92C_LEDCFG2_EN);
if (!on) {
@@ -920,15 +983,28 @@ rtwn_set_nettype(struct rtwn_softc *sc, enum ieee80211_opmode opmode)
void
rtwn_calib(struct rtwn_softc *sc)
{
- struct r92c_fw_cmd_rssi cmd;
if (sc->avg_pwdb != -1) {
- /* Indicate Rx signal strength to FW for rate adaptation. */
- memset(&cmd, 0, sizeof(cmd));
- cmd.macid = 0; /* BSS. */
- cmd.pwdb = sc->avg_pwdb;
DPRINTFN(3, ("sending RSSI command avg=%d\n", sc->avg_pwdb));
- rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
+
+ /* Indicate Rx signal strength to FW for rate adaptation. */
+ if (sc->chip & RTWN_CHIP_92E) {
+ struct r92e_fw_cmd_rssi cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.macid = 0; /* BSS. */
+ cmd.pwdb = sc->avg_pwdb;
+ rtwn_fw_cmd(sc, R92E_CMD_RSSI_REPORT, &cmd,
+ sizeof(cmd));
+ } else {
+ struct r92c_fw_cmd_rssi cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.macid = 0; /* BSS. */
+ cmd.pwdb = sc->avg_pwdb;
+ rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd,
+ sizeof(cmd));
+ }
}
/* Do temperature compensation. */
@@ -1120,7 +1196,7 @@ rtwn_update_short_preamble(struct ieee80211com *ic)
{
struct rtwn_softc *sc = ic->ic_softc;
- if (sc->chip & RTWN_CHIP_88E)
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))
rtwn_r88e_update_short_preamble(sc);
else
rtwn_r92c_update_short_preamble(sc);
@@ -1345,7 +1421,7 @@ rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
uint8_t rpt;
int8_t rssi;
- if (sc->chip & RTWN_CHIP_88E)
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))
return rtwn_r88e_get_rssi(sc, rate, physt);
if (rate <= 3) {
@@ -1524,7 +1600,7 @@ rtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
void
rtwn_fw_reset(struct rtwn_softc *sc)
{
- if (sc->chip & RTWN_CHIP_88E)
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))
rtwn_r88e_fw_reset(sc);
else
rtwn_r92c_fw_reset(sc);
@@ -1564,13 +1640,14 @@ rtwn_r88e_fw_reset(struct rtwn_softc *sc)
uint16_t reg;
/* Reset MCU IO wrapper. */
- rtwn_write_1(sc, R92C_RSV_CTRL + 1,
- rtwn_read_1(sc, R92C_RSV_CTRL + 1) & ~R92C_RSV_CTRL_WLOCK_08);
+ rtwn_write_2(sc, R92C_RSV_CTRL,
+ rtwn_read_2(sc, R92C_RSV_CTRL) & ~R88E_RSV_CTRL_MIO_EN);
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
+
/* Enable MCU IO wrapper. */
- rtwn_write_1(sc, R92C_RSV_CTRL + 1,
- rtwn_read_1(sc, R92C_RSV_CTRL) | R92C_RSV_CTRL_WLOCK_08);
+ rtwn_write_2(sc, R92C_RSV_CTRL,
+ rtwn_read_2(sc, R92C_RSV_CTRL) | R88E_RSV_CTRL_MIO_EN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
}
@@ -1599,7 +1676,8 @@ rtwn_load_firmware(struct rtwn_softc *sc)
if ((letoh16(hdr->signature) >> 4) == 0x230 ||
(letoh16(hdr->signature) >> 4) == 0x88c ||
(letoh16(hdr->signature) >> 4) == 0x88e ||
- (letoh16(hdr->signature) >> 4) == 0x92c) {
+ (letoh16(hdr->signature) >> 4) == 0x92c ||
+ (letoh16(hdr->signature) >> 4) == 0x92e) {
DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n",
letoh16(hdr->version), letoh16(hdr->subversion),
hdr->month, hdr->date, hdr->hour, hdr->minute));
@@ -1627,6 +1705,7 @@ rtwn_load_firmware(struct rtwn_softc *sc)
rtwn_write_1(sc, R92C_MCUFWDL,
rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT);
+ DELAY(50);
for (page = 0; len > 0; page++) {
mlen = MIN(len, R92C_FW_PAGE_SIZE);
error = sc->sc_ops.fw_loadpage(sc->sc_ops.cookie, page, ptr,
@@ -1696,6 +1775,8 @@ rtwn_rf_init(struct rtwn_softc *sc)
/* Select RF programming based on board type. */
if (sc->chip & RTWN_CHIP_88E)
prog = rtl8188eu_rf_prog;
+ else if (sc->chip & RTWN_CHIP_92E)
+ prog = rtl8192e_rf_prog;
else if (!(sc->chip & RTWN_CHIP_92C)) {
if (sc->board_type == R92C_BOARD_TYPE_MINICARD)
prog = rtl8188ce_rf_prog;
@@ -1717,36 +1798,47 @@ rtwn_rf_init(struct rtwn_softc *sc)
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
reg |= 0x100000;
rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
- DELAY(1);
+ DELAY(50);
/* Set RF_ENV output high. */
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
reg |= 0x10;
rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
- DELAY(1);
+ DELAY(50);
/* Set address and data lengths of RF registers. */
reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH;
rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
- DELAY(1);
+ DELAY(50);
reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH;
rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
- DELAY(1);
+ DELAY(50);
/* Write RF initialization values for this chain. */
for (j = 0; j < prog[i].count; j++) {
- if (prog[i].regs[j] >= 0xf9 &&
- prog[i].regs[j] <= 0xfe) {
- /*
- * These are fake RF registers offsets that
- * indicate a delay is required.
- */
+ switch (prog[i].regs[j]) {
+ case 0xfe:
+ DELAY(50000);
+ continue;
+ case 0xfd:
+ DELAY(5000);
+ continue;
+ case 0xfc:
+ DELAY(1000);
+ continue;
+ case 0xfb:
DELAY(50);
continue;
+ case 0xfa:
+ DELAY(5);
+ continue;
+ case 0xf9:
+ DELAY(1);
+ continue;
}
rtwn_rf_write(sc, i, prog[i].regs[j],
prog[i].vals[j]);
- DELAY(1);
+ DELAY(5);
}
/* Restore RF_ENV control type. */
@@ -1863,7 +1955,7 @@ rtwn_edca_init(struct rtwn_softc *sc)
void
rtwn_rate_fallback_init(struct rtwn_softc *sc)
{
- if (!(sc->chip & RTWN_CHIP_88E)) {
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
if (sc->chip & RTWN_CHIP_PCI) {
rtwn_write_4(sc, R92C_DARFRC + 0, 0x01000000);
rtwn_write_4(sc, R92C_DARFRC + 4, 0x07060504);
@@ -1884,19 +1976,34 @@ rtwn_usb_aggr_init(struct rtwn_softc *sc)
uint32_t reg;
int dmasize, dmatiming, ndesc;
- dmasize = 48;
- dmatiming = 4;
- ndesc = (sc->chip & RTWN_CHIP_88E) ? 1 : 6;
+ if (sc->chip & RTWN_CHIP_92E) {
+ dmasize = 0x06;
+ dmatiming = 0x20;
+ ndesc = 3;
+ } else {
+ dmasize = 48;
+ dmatiming = 4;
+ ndesc = (sc->chip & RTWN_CHIP_88E) ? 1 : 6;
+ }
/* Tx aggregation setting. */
- reg = rtwn_read_4(sc, R92C_TDECTRL);
- reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, ndesc);
- rtwn_write_4(sc, R92C_TDECTRL, reg);
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_1(sc, R92E_DWBCN1_CTRL, ndesc << 1);
+ } else {
+ reg = rtwn_read_4(sc, R92C_TDECTRL);
+ reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, ndesc);
+ rtwn_write_4(sc, R92C_TDECTRL, reg);
+ }
/* Rx aggregation setting. */
- rtwn_write_1(sc, R92C_TRXDMA_CTRL,
- rtwn_read_1(sc, R92C_TRXDMA_CTRL) |
- R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_1(sc, R92E_RXDMA_PRO,
+ (rtwn_read_1(sc, R92E_RXDMA_PRO) & ~0x20) | 0x1e);
+ } else {
+ rtwn_write_1(sc, R92C_TRXDMA_CTRL,
+ rtwn_read_1(sc, R92C_TRXDMA_CTRL) |
+ R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
+ }
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, dmasize);
if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C))
rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, dmatiming);
@@ -1972,6 +2079,8 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
{
if (sc->chip & RTWN_CHIP_88E)
rtwn_r88e_get_txpower(sc, chain, c, extc, power);
+ else if (sc->chip & RTWN_CHIP_92E)
+ rtwn_r92e_get_txpower(sc, chain, c, extc, power);
else
rtwn_r92c_get_txpower(sc, chain, c, extc, power);
}
@@ -2076,6 +2185,68 @@ rtwn_r92c_get_txpower(struct rtwn_softc *sc, int chain,
}
void
+rtwn_r92e_get_txpower(struct rtwn_softc *sc, int chain,
+ struct ieee80211_channel *c, struct ieee80211_channel *extc,
+ uint16_t power[RTWN_POWER_COUNT])
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct r92e_rom *rom = &sc->sc_r92e_rom;
+ struct r92e_tx_pwr *txpwr;
+ uint8_t cckpow, ofdmpow;
+ int8_t diff;
+ int ridx, chan, group;
+
+ /* Determine channel group. */
+ chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
+ if (chan <= 2)
+ group = 0;
+ else if (chan <= 5)
+ group = 1;
+ else if (chan <= 8)
+ group = 2;
+ else if (chan <= 11)
+ group = 3;
+ else
+ group = 4;
+
+ memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
+
+ if (chain == 0)
+ txpwr = &rom->txpwr_a;
+ else
+ txpwr = &rom->txpwr_b;
+
+ /* Compute per-CCK rate Tx power. */
+ cckpow = txpwr->cck_tx_pwr[group];
+ for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
+ power[ridx] = cckpow;
+ if (power[ridx] > R92C_MAX_TX_PWR)
+ power[ridx] = R92C_MAX_TX_PWR;
+ }
+
+ /* Compute per-OFDM rate Tx power. */
+ diff = RTWN_SIGN4TO8(MS(txpwr->ht20_ofdm_tx_pwr_diff,
+ R92E_ROM_TXPWR_OFDM_DIFF));
+ ofdmpow = txpwr->ht40_tx_pwr[group] + diff;
+ for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
+ power[ridx] = ofdmpow;
+ if (power[ridx] > R92C_MAX_TX_PWR)
+ power[ridx] = R92C_MAX_TX_PWR;
+ }
+
+ /* Compute per-MCS Tx power. */ /* XXX apparently need to handle tx chains here? */
+ if (extc == NULL)
+ diff = RTWN_SIGN4TO8(MS(txpwr->ht20_ofdm_tx_pwr_diff,
+ R92E_ROM_TXPWR_HT20_DIFF));
+
+ for (ridx = RTWN_RIDX_MCS0; ridx < RTWN_RIDX_MCS8; ridx++) {
+ power[ridx] = txpwr->ht40_tx_pwr[group] + diff;
+ if (power[ridx] > R92C_MAX_TX_PWR)
+ power[ridx] = R92C_MAX_TX_PWR;
+ }
+}
+
+void
rtwn_r88e_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[RTWN_POWER_COUNT])
@@ -2158,6 +2329,7 @@ rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
{
struct ieee80211com *ic = &sc->sc_ic;
u_int chan;
+ uint32_t reg;
int i;
chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
@@ -2165,18 +2337,24 @@ rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
/* Set Tx power for this new channel. */
rtwn_set_txpower(sc, c, extc);
- for (i = 0; i < sc->nrxchains; i++) {
- rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
- RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
- }
if (extc != NULL) {
uint32_t reg;
/* Is secondary channel below or above primary? */
int prichlo = c->ic_freq < extc->ic_freq;
- rtwn_write_1(sc, R92C_BWOPMODE,
- rtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ);
+ if (sc->chip & RTWN_CHIP_92E) {
+ uint16_t reg;
+ reg = rtwn_read_2(sc, R92C_WMAC_TRXPTCL_CTL);
+ reg &= ~R92C_WMAC_TRXPTCL_CTL_BW_MASK;
+ reg |= R92C_WMAC_TRXPTCL_CTL_BW_40;
+ rtwn_write_2(sc, R92C_WMAC_TRXPTCL_CTL, reg);
+ rtwn_write_1(sc, R92E_DATA_SC, 0);
+ } else {
+ rtwn_write_1(sc, R92C_BWOPMODE,
+ rtwn_read_1(sc, R92C_BWOPMODE) &
+ ~R92C_BWOPMODE_20MHZ);
+ }
reg = rtwn_read_1(sc, R92C_RRSR + 2);
reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5;
@@ -2196,7 +2374,7 @@ rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10;
rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
- if (!(sc->chip & RTWN_CHIP_88E)) {
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) &
~R92C_FPGA0_ANAPARAM2_CBW20);
@@ -2207,28 +2385,45 @@ rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
rtwn_bb_write(sc, 0x818, reg);
/* Select 40MHz bandwidth. */
- rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
- (sc->rf_chnlbw[0] & ~0xfff) | chan);
+ for (i = 0; i < sc->nrxchains; i++) {
+ rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
+ (sc->rf_chnlbw[i] & ~0xfff) | chan);
+ }
} else {
- rtwn_write_1(sc, R92C_BWOPMODE,
- rtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ);
+ if (sc->chip & RTWN_CHIP_92E) {
+ uint16_t reg;
+ reg = rtwn_read_2(sc, R92C_WMAC_TRXPTCL_CTL);
+ reg &= ~R92C_WMAC_TRXPTCL_CTL_BW_MASK;
+ rtwn_write_2(sc, R92C_WMAC_TRXPTCL_CTL, reg);
+ rtwn_write_1(sc, R92E_DATA_SC, 0);
+ } else {
+ rtwn_write_1(sc, R92C_BWOPMODE,
+ rtwn_read_1(sc, R92C_BWOPMODE) |
+ R92C_BWOPMODE_20MHZ);
+ }
rtwn_bb_write(sc, R92C_FPGA0_RFMOD,
rtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ);
rtwn_bb_write(sc, R92C_FPGA1_RFMOD,
rtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ);
- if (!(sc->chip & RTWN_CHIP_88E)) {
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) |
R92C_FPGA0_ANAPARAM2_CBW20);
+ } else if (sc->chip & RTWN_CHIP_92E) {
+ reg = rtwn_read_4(sc, R92C_OFDM0_TX_PSDO_NOISE_WEIGHT);
+ reg &= ~0xc0000000;
+ rtwn_write_4(sc, R92C_OFDM0_TX_PSDO_NOISE_WEIGHT, reg);
}
/* Select 20MHz bandwidth. */
- rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
- (sc->rf_chnlbw[0] & ~0xfff) | chan |
- ((sc->chip & RTWN_CHIP_88E) ? R88E_RF_CHNLBW_BW20 :
- R92C_RF_CHNLBW_BW20));
+ for (i = 0; i < sc->nrxchains; i++) {
+ rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
+ (sc->rf_chnlbw[i] & ~0xfff) | chan |
+ ((sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)) ?
+ R88E_RF_CHNLBW_BW20 : R92C_RF_CHNLBW_BW20));
+ }
}
if (sc->chip == (RTWN_CHIP_88E | RTWN_CHIP_PCI))
@@ -2241,33 +2436,48 @@ rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
{
uint32_t status;
int offset = chain * 0x20;
+ uint32_t iqk_tone_92c[] = {
+ 0x10008c1f, 0x10008c1f, 0x82140102, 0x28160202, 0x10008c22
+ };
+ uint32_t iqk_tone_92e[] = {
+ 0x18008c1c, 0x38008c1c, 0x82140303, 0x68160000, 0x38008c1c
+ };
+ uint32_t *iqk_tone;
+
+ if (sc->chip & RTWN_CHIP_92E)
+ iqk_tone = iqk_tone_92e;
+ else
+ iqk_tone = iqk_tone_92c;
if (chain == 0) { /* IQ calibration for chain 0. */
/* IQ calibration settings for chain 0. */
- rtwn_bb_write(sc, 0xe30, 0x10008c1f);
- rtwn_bb_write(sc, 0xe34, 0x10008c1f);
- rtwn_bb_write(sc, 0xe38, 0x82140102);
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE_A, iqk_tone[0]);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE_B, iqk_tone[1]);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI_A, iqk_tone[2]);
if (sc->ntxchains > 1) {
- rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */
+ rtwn_bb_write(sc, R92C_RX_IQK_PI_A, iqk_tone[3]);
/* IQ calibration settings for chain 1. */
- rtwn_bb_write(sc, 0xe50, 0x10008c22);
- rtwn_bb_write(sc, 0xe54, 0x10008c22);
- rtwn_bb_write(sc, 0xe58, 0x82140102);
- rtwn_bb_write(sc, 0xe5c, 0x28160202);
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE_B, iqk_tone[4]);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE_B, iqk_tone[4]);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI_B, 0x82140102);
+ rtwn_bb_write(sc, R92C_RX_IQK_PI_B, 0x28160202);
} else
- rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */
+ rtwn_bb_write(sc, R92C_RX_IQK_PI_A, 0x28160502);
/* LO calibration settings. */
- rtwn_bb_write(sc, 0xe4c, 0x001028d1);
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x00462911);
+ else
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1);
/* We're doing LO and IQ calibration in one shot. */
- rtwn_bb_write(sc, 0xe48, 0xf9000000);
- rtwn_bb_write(sc, 0xe48, 0xf8000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
} else { /* IQ calibration for chain 1. */
/* We're doing LO and IQ calibration in one shot. */
- rtwn_bb_write(sc, 0xe60, 0x00000002);
- rtwn_bb_write(sc, 0xe60, 0x00000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0x00000002);
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0x00000000);
}
/* Give LO and IQ calibrations the time to complete. */
@@ -2279,16 +2489,20 @@ rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
if (status & (1 << (28 + chain * 3)))
return (0); /* Tx failed. */
/* Read Tx IQ calibration results. */
- tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
- tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
+ tx[0] = (rtwn_bb_read(sc, R92C_TX_POWER_BEFORE_IQK_A + offset) >> 16)
+ & 0x3ff;
+ tx[1] = (rtwn_bb_read(sc, R92C_TX_POWER_AFTER_IQK_A + offset) >> 16)
+ & 0x3ff;
if (tx[0] == 0x142 || tx[1] == 0x042)
return (0); /* Tx failed. */
if (status & (1 << (27 + chain * 3)))
return (1); /* Rx failed. */
/* Read Rx IQ calibration results. */
- rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
- rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
+ rx[0] = (rtwn_bb_read(sc, R92C_RX_POWER_BEFORE_IQK_A_2 + offset) >> 16)
+ & 0x3ff;
+ rx[1] = (rtwn_bb_read(sc, R92C_RX_POWER_AFTER_IQK_A_2 + offset) >> 16)
+ & 0x3ff;
if (rx[0] == 0x132 || rx[1] == 0x036)
return (1); /* Rx failed. */
@@ -2305,8 +2519,25 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
0xe88, 0xe8c, 0xed0, 0xed4,
0xed8, 0xedc, 0xee0, 0xeec
};
+ static const uint32_t adda_92c[] = {
+ 0x0b1b25a0, 0x0bdb25a0, 0x04db25a4, 0x0b1b25a4
+ };
+ static const uint32_t adda_92e[] = {
+ 0x0fc01616, 0x0fc01616, 0x0fc01616, 0x0fc01616
+ };
+ const uint32_t *adda_vals;
+
int i, chain;
- uint32_t hssi_param1;
+ uint32_t hssi_param1, reg;
+ uint8_t xa_agc, xb_agc;
+
+ xa_agc = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)) & 0xff;
+ xb_agc = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)) & 0xff;
+
+ if (sc->chip & RTWN_CHIP_92E)
+ adda_vals = adda_92e;
+ else
+ adda_vals = adda_92c;
if (n == 0) {
for (i = 0; i < nitems(reg_adda); i++)
@@ -2319,20 +2550,12 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
}
if (sc->ntxchains == 1) {
- rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
+ rtwn_bb_write(sc, reg_adda[0], adda_vals[0]);
for (i = 1; i < nitems(reg_adda); i++)
- rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
+ rtwn_bb_write(sc, reg_adda[i], adda_vals[1]);
} else {
for (i = 0; i < nitems(reg_adda); i++)
- rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
- }
-
- hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
- if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
- rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
- hssi_param1 | R92C_HSSI_PARAM1_PI);
- rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
- hssi_param1 | R92C_HSSI_PARAM1_PI);
+ rtwn_bb_write(sc, reg_adda[i], adda_vals[2]);
}
if (n == 0) {
@@ -2340,21 +2563,61 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
iq_cal_regs->ofdm0_trmuxpar =
rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
+ iq_cal_regs->fpga0_rfifacesw0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
iq_cal_regs->fpga0_rfifacesw1 =
rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
+ iq_cal_regs->fpga0_rfifaceoe0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
+ iq_cal_regs->fpga0_rfifaceoe1 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1));
+ iq_cal_regs->config_ant_a =
+ rtwn_bb_read(sc, R92C_CONFIG_ANT_A);
+ iq_cal_regs->config_ant_b =
+ rtwn_bb_read(sc, R92C_CONFIG_ANT_B);
+ iq_cal_regs->cck0_afesetting =
+ rtwn_bb_read(sc, R92C_CCK0_AFESETTING);
+ }
+
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_4(sc, R92C_CCK0_AFESETTING, rtwn_read_4(sc,
+ R92C_CCK0_AFESETTING) | 0x0f000000);
+ } else {
+ hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ }
}
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
- rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
- if (sc->ntxchains > 1) {
- rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
- rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
- }
- rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_AC_VO |
- R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE | R92C_TXPAUSE_AC_BK |
- R92C_TXPAUSE_MGNT | R92C_TXPAUSE_HIGH);
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22208200);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0),
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0)) | (1 << 10) |
+ (1 << 26));
+
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), rtwn_bb_read(sc,
+ R92C_FPGA0_RFIFACEOE(0)) | (1 << 10));
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), rtwn_bb_read(sc,
+ R92C_FPGA0_RFIFACEOE(1)) | (1 << 10));
+ } else {
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
+
+ if (sc->ntxchains > 1) {
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
+ }
+
+ rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_AC_VO |
+ R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE |
+ R92C_TXPAUSE_AC_BK | R92C_TXPAUSE_MGNT |
+ R92C_TXPAUSE_HIGH);
+ }
rtwn_write_1(sc, R92C_BCN_CTRL,
iq_cal_regs->bcn_ctrl & ~(R92C_BCN_CTRL_EN_BCN));
rtwn_write_1(sc, R92C_BCN_CTRL1,
@@ -2362,26 +2625,26 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
rtwn_write_1(sc, R92C_GPIO_MUXCFG,
iq_cal_regs->gpio_muxcfg & ~(R92C_GPIO_MUXCFG_ENBT));
- rtwn_bb_write(sc, 0x0b68, 0x00080000);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT_A, 0x00080000);
if (sc->ntxchains > 1)
- rtwn_bb_write(sc, 0x0b6c, 0x00080000);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT_B, 0x00080000);
- rtwn_bb_write(sc, 0x0e28, 0x80800000);
- rtwn_bb_write(sc, 0x0e40, 0x01007c00);
- rtwn_bb_write(sc, 0x0e44, 0x01004800);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
- rtwn_bb_write(sc, 0x0b68, 0x00080000);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT_A, 0x00080000);
for (chain = 0; chain < sc->ntxchains; chain++) {
if (chain > 0) {
/* Put chain 0 on standby. */
- rtwn_bb_write(sc, 0x0e28, 0x00);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
- rtwn_bb_write(sc, 0x0e28, 0x80800000);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
/* Enable chain 1. */
for (i = 0; i < nitems(reg_adda); i++)
- rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
+ rtwn_bb_write(sc, reg_adda[i], adda_vals[3]);
}
/* Run IQ calibration twice. */
@@ -2413,21 +2676,22 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]));
}
- rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
- iq_cal_regs->ofdm0_trxpathena);
- rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
- iq_cal_regs->fpga0_rfifacesw1);
- rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, iq_cal_regs->ofdm0_trmuxpar);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
- rtwn_bb_write(sc, 0x0e28, 0x00);
- rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
- if (sc->ntxchains > 1)
- rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
+ if (!(sc->chip & RTWN_CHIP_92E)) {
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
+ if (sc->ntxchains > 1)
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
+ }
if (n != 0) {
- if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
- rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
- rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
+ if (!(sc->chip & RTWN_CHIP_92E)) {
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
+ hssi_param1);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
+ hssi_param1);
+ }
}
for (i = 0; i < nitems(reg_adda); i++)
@@ -2437,6 +2701,38 @@ rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs->bcn_ctrl);
rtwn_write_1(sc, R92C_BCN_CTRL1, iq_cal_regs->bcn_ctrl1);
rtwn_write_4(sc, R92C_GPIO_MUXCFG, iq_cal_regs->gpio_muxcfg);
+
+ rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
+ iq_cal_regs->ofdm0_trxpathena);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0),
+ iq_cal_regs->fpga0_rfifacesw0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
+ iq_cal_regs->fpga0_rfifacesw1);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0),
+ iq_cal_regs->fpga0_rfifaceoe0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1),
+ iq_cal_regs->fpga0_rfifaceoe1);
+ rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR,
+ iq_cal_regs->ofdm0_trmuxpar);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT_A,
+ iq_cal_regs->config_ant_a);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT_B,
+ iq_cal_regs->config_ant_b);
+ rtwn_bb_write(sc, R92C_CCK0_AFESETTING,
+ iq_cal_regs->cck0_afesetting);
+
+ reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
+ reg &= ~0xff;
+ rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg | 0x50);
+ rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg | xa_agc);
+
+ reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
+ reg &= ~0xff;
+ rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg | 0x50);
+ rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg | xb_agc);
+
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE_A, 0x01008c00);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE_A, 0x01008c00);
}
}
@@ -2618,18 +2914,26 @@ rtwn_lc_calib(struct rtwn_softc *sc)
void
rtwn_temp_calib(struct rtwn_softc *sc)
{
- int temp;
+ int temp, t_meter_reg, t_meter_val;
+
+ if (sc->chip & RTWN_CHIP_92E) {
+ t_meter_reg = R92E_RF_T_METER;
+ t_meter_val = 0x37cf8;
+ } else {
+ t_meter_reg = R92C_RF_T_METER;
+ t_meter_val = 0x60;
+ }
if (sc->thcal_state == 0) {
/* Start measuring temperature. */
- rtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60);
+ rtwn_rf_write(sc, 0, t_meter_reg, t_meter_val);
sc->thcal_state = 1;
return;
}
sc->thcal_state = 0;
/* Read measured temperature. */
- temp = rtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f;
+ temp = rtwn_rf_read(sc, 0, t_meter_reg) & 0x1f;
if (temp == 0) /* Read failed, skip. */
return;
DPRINTFN(2, ("temperature=%d\n", temp));
@@ -2654,7 +2958,10 @@ rtwn_temp_calib(struct rtwn_softc *sc)
void
rtwn_enable_intr(struct rtwn_softc *sc)
{
- if (sc->chip & RTWN_CHIP_88E) {
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_4(sc, R88E_HIMR, 0);
+ rtwn_write_4(sc, R88E_HIMRE, 0);
+ } else if (sc->chip & RTWN_CHIP_88E) {
rtwn_write_4(sc, R88E_HISR, 0xffffffff);
if (sc->chip & RTWN_CHIP_USB) {
rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM |
@@ -2813,7 +3120,7 @@ rtwn_init(struct ifnet *ifp)
rtwn_write_1(sc, R92C_BCNDMATIM, R92C_BCNDMATIM_INIT_TIME);
rtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
- if (!(sc->chip & RTWN_CHIP_88E)) {
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
/* Setup AMPDU aggregation. */
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
@@ -2837,7 +3144,7 @@ rtwn_init(struct ifnet *ifp)
sc->sc_ops.bb_init(sc->sc_ops.cookie);
rtwn_rf_init(sc);
- if (sc->chip & RTWN_CHIP_88E) {
+ if (sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)) {
rtwn_write_2(sc, R92C_CR,
rtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN |
R92C_CR_MACRXEN);
@@ -2857,18 +3164,28 @@ rtwn_init(struct ifnet *ifp)
/* Enable hardware sequence numbering. */
rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
+ if (sc->chip & RTWN_CHIP_92E) {
+ rtwn_write_4(sc, R92C_BAR_MODE_CTRL, 0x0201ffff);
+ rtwn_write_1(sc, R92C_NAV_UPPER, 0);
+
+ rtwn_write_1(sc, R92C_QUEUE_CTRL,
+ rtwn_read_1(sc, R92C_QUEUE_CTRL) & ~0x08);
+ }
+
/* Perform LO and IQ calibrations. */
rtwn_iq_calib(sc);
/* Perform LC calibration. */
rtwn_lc_calib(sc);
/* Fix USB interference issue. */
- if ((sc->chip & RTWN_CHIP_USB) && !(sc->chip & RTWN_CHIP_88E)) {
- rtwn_write_1(sc, 0xfe40, 0xe0);
- rtwn_write_1(sc, 0xfe41, 0x8d);
- rtwn_write_1(sc, 0xfe42, 0x80);
+ if (sc->chip & RTWN_CHIP_USB) {
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
+ rtwn_write_1(sc, 0xfe40, 0xe0);
+ rtwn_write_1(sc, 0xfe41, 0x8d);
+ rtwn_write_1(sc, 0xfe42, 0x80);
- rtwn_pa_bias_init(sc);
+ rtwn_pa_bias_init(sc);
+ }
}
/* Initialize GPIO setting. */
@@ -2876,7 +3193,7 @@ rtwn_init(struct ifnet *ifp)
rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT);
/* Fix for lower temperature. */
- if (!(sc->chip & RTWN_CHIP_88E))
+ if (!(sc->chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)))
rtwn_write_1(sc, 0x15, 0xe9);
/* Set default channel. */
diff --git a/sys/dev/ic/rtwnvar.h b/sys/dev/ic/rtwnvar.h
index 885332dad9e..6386e4c9e07 100644
--- a/sys/dev/ic/rtwnvar.h
+++ b/sys/dev/ic/rtwnvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtwnvar.h,v 1.13 2018/10/01 22:36:08 jmatthew Exp $ */
+/* $OpenBSD: rtwnvar.h,v 1.14 2018/12/04 10:47:32 jmatthew Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -102,10 +102,12 @@ struct rtwn_softc {
int fwcur;
union {
struct r92c_rom r92c_rom;
+ struct r92e_rom r92e_rom;
struct r88e_rom r88e_rom;
struct r23a_rom r23a_rom;
} u;
#define sc_r92c_rom u.r92c_rom
+#define sc_r92e_rom u.r92e_rom
#define sc_r88e_rom u.r88e_rom
#define sc_r23a_rom u.r23a_rom
diff --git a/sys/dev/usb/if_urtwn.c b/sys/dev/usb/if_urtwn.c
index 325edba3fd9..43d924c69c9 100644
--- a/sys/dev/usb/if_urtwn.c
+++ b/sys/dev/usb/if_urtwn.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: if_urtwn.c,v 1.79 2018/10/01 11:03:46 jmatthew Exp $ */
+/* $OpenBSD: if_urtwn.c,v 1.80 2018/12/04 10:47:32 jmatthew Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
+ * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,7 +19,8 @@
*/
/*
- * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU.
+ * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU/
+ * RTL8192EU.
*/
#include "bpfilter.h"
@@ -34,6 +36,7 @@
#include <sys/device.h>
#include <sys/endian.h>
+#include <machine/bus.h>
#include <machine/intr.h>
#if NBPFILTER > 0
@@ -52,6 +55,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
@@ -68,6 +72,7 @@
#define R92C_TX_PAGE_COUNT 248
#define R92C_TX_PAGE_BOUNDARY (R92C_TX_PAGE_COUNT + 1)
#define R92C_MAX_RX_DMA_SIZE 0x2800
+
#define R88E_HQ_NPAGES 0
#define R88E_LQ_NPAGES 9
#define R88E_NQ_NPAGES 0
@@ -76,6 +81,16 @@
#define R88E_TX_PAGE_BOUNDARY (R88E_TX_PAGE_COUNT + 1)
#define R88E_MAX_RX_DMA_SIZE 0x2400
+#define R92E_HQ_NPAGES 16
+#define R92E_LQ_NPAGES 16
+#define R92E_NQ_NPAGES 16
+#define R92E_TX_PAGE_COUNT 248
+#define R92E_TX_PAGE_BOUNDARY (R92E_TX_PAGE_COUNT + 1)
+#define R92E_MAX_RX_DMA_SIZE 0x3fc0
+
+#define R92C_TXDESC_SUMSIZE 32
+#define R92C_TXDESC_SUMOFFSET 14
+
/* USB Requests. */
#define R92C_REQ_REGS 0x05
@@ -87,7 +102,7 @@
#define URTWN_HOST_CMD_RING_COUNT 32
#define URTWN_RXBUFSZ (16 * 1024)
-#define URTWN_TXBUFSZ (sizeof(struct r92c_tx_desc_usb) + IEEE80211_MAX_LEN)
+#define URTWN_TXBUFSZ (sizeof(struct r92e_tx_desc_usb) + IEEE80211_MAX_LEN)
#define URTWN_RIDX_COUNT 28
@@ -219,6 +234,7 @@ int urtwn_debug = 4;
{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) | RTWN_CHIP_USB }
#define URTWN_DEV_8192CU(v, p) URTWN_DEV(v, p, RTWN_CHIP_92C | RTWN_CHIP_88C)
#define URTWN_DEV_8188EU(v, p) URTWN_DEV(v, p, RTWN_CHIP_88E)
+#define URTWN_DEV_8192EU(v, p) URTWN_DEV(v, p, RTWN_CHIP_92E)
static const struct urtwn_type {
struct usb_devno dev;
uint32_t chip;
@@ -312,7 +328,10 @@ static const struct urtwn_type {
URTWN_DEV_8188EU(ELECOM, WDC150SU2M),
URTWN_DEV_8188EU(REALTEK, RTL8188ETV),
URTWN_DEV_8188EU(REALTEK, RTL8188EU),
- URTWN_DEV_8188EU(TPLINK, RTL8188EUS)
+ URTWN_DEV_8188EU(TPLINK, RTL8188EUS),
+ /* URTWN_RTL8192EU */
+ URTWN_DEV_8192EU(REALTEK, RTL8192EU),
+ URTWN_DEV_8192EU(DLINK, DWA131E1)
};
#define urtwn_lookup(v, p) \
@@ -370,6 +389,7 @@ int urtwn_ioctl(struct ifnet *, u_long, caddr_t);
int urtwn_power_on(void *);
int urtwn_alloc_buffers(void *);
int urtwn_r92c_power_on(struct urtwn_softc *);
+int urtwn_r92e_power_on(struct urtwn_softc *);
int urtwn_r88e_power_on(struct urtwn_softc *);
int urtwn_llt_init(struct urtwn_softc *, int);
int urtwn_fw_loadpage(void *, int, uint8_t *, int);
@@ -1185,7 +1205,7 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv,
struct r92c_rx_desc_usb *rxd;
uint32_t rxdw0;
uint8_t *buf;
- int len, totlen, pktlen, infosz, npkts, error;
+ int len, totlen, pktlen, infosz, npkts, error, align;
if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
DPRINTF(("RX status=%d\n", status));
@@ -1227,8 +1247,34 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv,
goto resubmit;
}
+ } else if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ int type;
+ struct r92e_c2h_tx_rpt *txrpt;
+
+ if (letoh32(rxd->rxdw2) & R92E_RXDW2_RPT_C2H) {
+ if (len < sizeof(struct r92c_rx_desc_usb) + 2)
+ goto resubmit;
+
+ type = buf[sizeof(struct r92c_rx_desc_usb)];
+ switch (type) {
+ case R92C_C2HEVT_TX_REPORT:
+ buf += sizeof(struct r92c_rx_desc_usb) + 2;
+ txrpt = (struct r92e_c2h_tx_rpt *)buf;
+ if (MS(txrpt->rptb2, R92E_RPTB2_RETRY_CNT) > 0)
+ sc->amn.amn_retrycnt++;
+ if ((txrpt->rptb0 & (R92E_RPTB0_RETRY_OVER |
+ R92E_RPTB0_LIFE_EXPIRE)) == 0)
+ sc->amn.amn_txcnt++;
+ break;
+ default:
+ break;
+ }
+ goto resubmit;
+ }
}
+ align = (sc->sc_sc.chip & RTWN_CHIP_92E ? 7 : 127);
+
/* Process all of them. */
while (npkts-- > 0) {
if (__predict_false(len < sizeof(*rxd)))
@@ -1250,8 +1296,8 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv,
/* Process 802.11 frame. */
urtwn_rx_frame(sc, buf, pktlen);
- /* Next chunk is 128-byte aligned. */
- totlen = (totlen + 127) & ~127;
+ /* Handle chunk alignment. */
+ totlen = (totlen + align) & ~align;
buf += totlen;
len -= totlen;
}
@@ -1296,51 +1342,21 @@ urtwn_txeof(struct usbd_xfer *xfer, void *priv,
splx(s);
}
-int
-urtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni)
+void
+urtwn_tx_fill_desc(struct urtwn_softc *sc, uint8_t **txdp, struct mbuf *m,
+ struct ieee80211_frame *wh, struct ieee80211_key *k,
+ struct ieee80211_node *ni)
{
- struct urtwn_softc *sc = cookie;
- struct ieee80211com *ic = &sc->sc_sc.sc_ic;
- struct ieee80211_frame *wh;
- struct ieee80211_key *k = NULL;
- struct urtwn_tx_data *data;
struct r92c_tx_desc_usb *txd;
- struct usbd_pipe *pipe;
- uint16_t qos, sum;
- uint8_t raid, type, tid, qid;
- int i, hasqos, xferlen, error;
-
- wh = mtod(m, struct ieee80211_frame *);
- type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
-
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
- k = ieee80211_get_txkey(ic, wh, ni);
- if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
- return (ENOBUFS);
- wh = mtod(m, struct ieee80211_frame *);
- }
-
- if ((hasqos = ieee80211_has_qos(wh))) {
- qos = ieee80211_get_qos(wh);
- tid = qos & IEEE80211_QOS_TID;
- qid = ieee80211_up_to_ac(ic, tid);
- } else if (type != IEEE80211_FC0_TYPE_DATA) {
- /* Use AC VO for management frames. */
- qid = EDCA_AC_VO;
- } else
- qid = EDCA_AC_BE;
-
- /* Get the USB pipe to use for this AC. */
- pipe = sc->tx_pipe[sc->ac2idx[qid]];
-
- /* Grab a Tx buffer from our free list. */
- data = TAILQ_FIRST(&sc->tx_free_list);
- TAILQ_REMOVE(&sc->tx_free_list, data, next);
+ struct ieee80211com *ic = &sc->sc_sc.sc_ic;
+ uint8_t raid, type;
- /* Fill Tx descriptor. */
- txd = (struct r92c_tx_desc_usb *)data->buf;
+ txd = (struct r92c_tx_desc_usb *)*txdp;
+ (*txdp) += sizeof(*txd);
memset(txd, 0, sizeof(*txd));
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+
txd->txdw0 |= htole32(
SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
@@ -1426,18 +1442,145 @@ urtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni)
/* Set sequence number (already little endian). */
txd->txdseq |= (*(uint16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
- if (!hasqos) {
+ if (!ieee80211_has_qos(wh)) {
/* Use HW sequence numbering for non-QoS frames. */
txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
txd->txdseq |= htole16(R92C_TXDW3_HWSEQEN);
} else
txd->txdw4 |= htole32(R92C_TXDW4_QOS);
+}
+
+void
+urtwn_tx_fill_desc_gen2(struct urtwn_softc *sc, uint8_t **txdp, struct mbuf *m,
+ struct ieee80211_frame *wh, struct ieee80211_key *k,
+ struct ieee80211_node *ni)
+{
+ struct r92e_tx_desc_usb *txd;
+ struct ieee80211com *ic = &sc->sc_sc.sc_ic;
+ uint8_t raid, type;
+
+ txd = (struct r92e_tx_desc_usb *)*txdp;
+ (*txdp) += sizeof(*txd);
+ memset(txd, 0, sizeof(*txd));
+
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+
+ txd->txdw0 |= htole32(
+ SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
+ SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
+ R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+ txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
+
+#ifdef notyet
+ /* cipher */
+#endif
+
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+ type == IEEE80211_FC0_TYPE_DATA) {
+ if (ic->ic_curmode == IEEE80211_MODE_11B ||
+ (sc->sc_sc.sc_flags & RTWN_FLAG_FORCE_RAID_11B))
+ raid = R92E_RAID_11B;
+ else
+ raid = R92E_RAID_11BG;
+ txd->txdw1 |= htole32(
+ SM(R92E_TXDW1_MACID, R92C_MACID_BSS) |
+ SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) |
+ SM(R92C_TXDW1_RAID, raid));
+ /* Request TX status report for AMRR */
+ txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT | R88E_TXDW2_AGGBK);
+
+ if (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
+ txd->txdw4 |= htole32(R92C_TXDW4_RTSEN |
+ R92C_TXDW4_HWRTSEN);
+ } else if (ic->ic_flags & IEEE80211_F_USEPROT) {
+ if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
+ txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF |
+ R92C_TXDW4_HWRTSEN);
+ } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) {
+ txd->txdw4 |= htole32(R92C_TXDW4_RTSEN |
+ R92C_TXDW4_HWRTSEN);
+ }
+ }
+ txd->txdw5 |= htole32(0x0001ff00);
+
+ /* Use AMRR */
+ txd->txdw3 |= htole32(R92E_TXDW3_DRVRATE);
+ txd->txdw4 |= htole32(SM(R92E_TXDW4_RTSRATE, ni->ni_txrate));
+ txd->txdw4 |= htole32(SM(R92E_TXDW4_DATARATE, ni->ni_txrate));
+ } else {
+ txd->txdw1 |= htole32(
+ SM(R92E_TXDW1_MACID, 0) |
+ SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) |
+ SM(R92C_TXDW1_RAID, R92E_RAID_11B));
+
+ /* Force CCK1. */
+ txd->txdw3 |= htole32(R92E_TXDW3_DRVRATE);
+ txd->txdw4 |= htole32(SM(R92E_TXDW4_DATARATE, 0));
+ }
+ txd->txdw4 |= htole32(SM(R92E_TXDW4_DATARATEFB, 0x1f));
+
+ txd->txdseq2 |= htole16(SM(R92E_TXDSEQ2_HWSEQ, *(uint16_t *)wh->i_seq));
+
+ if (!ieee80211_has_qos(wh)) {
+ /* Use HW sequence numbering for non-QoS frames. */
+ txd->txdw7 |= htole16(R92C_TXDW3_HWSEQEN);
+ }
+}
+
+int
+urtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni)
+{
+ struct urtwn_softc *sc = cookie;
+ struct ieee80211com *ic = &sc->sc_sc.sc_ic;
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *k = NULL;
+ struct urtwn_tx_data *data;
+ struct usbd_pipe *pipe;
+ uint16_t qos, sum;
+ uint8_t tid, qid;
+ int i, xferlen, error;
+ uint8_t *txdp;
+
+ wh = mtod(m, struct ieee80211_frame *);
+
+ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ k = ieee80211_get_txkey(ic, wh, ni);
+ if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
+ return (ENOBUFS);
+ wh = mtod(m, struct ieee80211_frame *);
+ }
+
+ if (ieee80211_has_qos(wh)) {
+ qos = ieee80211_get_qos(wh);
+ tid = qos & IEEE80211_QOS_TID;
+ qid = ieee80211_up_to_ac(ic, tid);
+ } else if ((wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK)
+ != IEEE80211_FC0_TYPE_DATA) {
+ /* Use AC VO for management frames. */
+ qid = EDCA_AC_VO;
+ } else
+ qid = EDCA_AC_BE;
+
+ /* Get the USB pipe to use for this AC. */
+ pipe = sc->tx_pipe[sc->ac2idx[qid]];
+
+ /* Grab a Tx buffer from our free list. */
+ data = TAILQ_FIRST(&sc->tx_free_list);
+ TAILQ_REMOVE(&sc->tx_free_list, data, next);
+
+ /* Fill Tx descriptor. */
+ txdp = data->buf;
+ if (sc->sc_sc.chip & RTWN_CHIP_92E)
+ urtwn_tx_fill_desc_gen2(sc, &txdp, m, wh, k, ni);
+ else
+ urtwn_tx_fill_desc(sc, &txdp, m, wh, k, ni);
/* Compute Tx descriptor checksum. */
sum = 0;
- for (i = 0; i < sizeof(*txd) / 2; i++)
- sum ^= ((uint16_t *)txd)[i];
- txd->txdsum = sum; /* NB: already little endian. */
+ for (i = 0; i < R92C_TXDESC_SUMSIZE / 2; i++)
+ sum ^= ((uint16_t *)data->buf)[i];
+ ((uint16_t *)data->buf)[R92C_TXDESC_SUMOFFSET] = sum;
#if NBPFILTER > 0
if (__predict_false(sc->sc_drvbpf != NULL)) {
@@ -1458,8 +1601,8 @@ urtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni)
}
#endif
- xferlen = sizeof(*txd) + m->m_pkthdr.len;
- m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&txd[1]);
+ xferlen = (txdp - data->buf) + m->m_pkthdr.len;
+ m_copydata(m, 0, m->m_pkthdr.len, txdp);
m_freem(m);
data->pipe = pipe;
@@ -1580,6 +1723,80 @@ urtwn_r92c_power_on(struct urtwn_softc *sc)
}
int
+urtwn_r92e_power_on(struct urtwn_softc *sc)
+{
+ uint32_t reg;
+ int ntries;
+
+ if (urtwn_read_4(sc, R92C_SYS_CFG) & R92E_SYS_CFG_SPSLDO_SEL) {
+ /* LDO. */
+ urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0xc3);
+ } else {
+ reg = urtwn_read_4(sc, R92C_SYS_SWR_CTRL2);
+ reg &= 0xff0fffff;
+ reg |= 0x00500000;
+ urtwn_write_4(sc, R92C_SYS_SWR_CTRL2, reg);
+ urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0x83);
+ }
+
+ /* 40MHz crystal source */
+ urtwn_write_1(sc, R92C_AFE_PLL_CTRL,
+ urtwn_read_1(sc, R92C_AFE_PLL_CTRL) & 0xfb);
+ urtwn_write_4(sc, R92C_AFE_XTAL_CTRL_EXT,
+ urtwn_read_4(sc, R92C_AFE_XTAL_CTRL_EXT) & 0xfffffc7f);
+
+ urtwn_write_1(sc, R92C_AFE_PLL_CTRL,
+ urtwn_read_1(sc, R92C_AFE_PLL_CTRL) & 0xbf);
+ urtwn_write_4(sc, R92C_AFE_XTAL_CTRL_EXT,
+ urtwn_read_4(sc, R92C_AFE_XTAL_CTRL_EXT) & 0xffdfffff);
+
+ /* Disable HWPDN. */
+ urtwn_write_2(sc, R92C_APS_FSMCO,
+ urtwn_read_2(sc, R92C_APS_FSMCO) & ~R92C_APS_FSMCO_APDM_HPDN);
+ for (ntries = 0; ntries < 5000; ntries++) {
+ if (urtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
+ break;
+ DELAY(10);
+ }
+ if (ntries == 5000) {
+ printf("%s: timeout waiting for chip power up\n",
+ sc->sc_dev.dv_xname);
+ return (ETIMEDOUT);
+ }
+
+ /* Disable WL suspend. */
+ urtwn_write_2(sc, R92C_APS_FSMCO,
+ urtwn_read_2(sc, R92C_APS_FSMCO) &
+ ~(R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE));
+
+ /* Auto enable WLAN. */
+ urtwn_write_4(sc, R92C_APS_FSMCO,
+ urtwn_read_4(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_RDY_MACON);
+ urtwn_write_2(sc, R92C_APS_FSMCO,
+ urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC);
+ for (ntries = 0; ntries < 5000; ntries++) {
+ if (!(urtwn_read_2(sc, R92C_APS_FSMCO) &
+ R92C_APS_FSMCO_APFM_ONMAC))
+ break;
+ DELAY(10);
+ }
+ if (ntries == 5000) {
+ printf("%s: timeout waiting for MAC auto ON\n",
+ sc->sc_dev.dv_xname);
+ return (ETIMEDOUT);
+ }
+
+ /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
+ urtwn_write_2(sc, R92C_CR, 0);
+ reg = urtwn_read_2(sc, R92C_CR);
+ reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
+ R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
+ R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC | R92C_CR_CALTMR_EN;
+ urtwn_write_2(sc, R92C_CR, reg);
+ return (0);
+}
+
+int
urtwn_r88e_power_on(struct urtwn_softc *sc)
{
uint32_t reg;
@@ -1672,6 +1889,22 @@ urtwn_llt_init(struct urtwn_softc *sc, int page_count)
}
int
+urtwn_auto_llt_init(struct urtwn_softc *sc)
+{
+ int ntries;
+
+ urtwn_write_4(sc, R92E_AUTO_LLT, urtwn_read_4(sc,
+ R92E_AUTO_LLT) | R92E_AUTO_LLT_EN);
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if (!(urtwn_read_4(sc, R92E_AUTO_LLT) & R92E_AUTO_LLT_EN))
+ return (0);
+ DELAY(2);
+ }
+
+ return (ETIMEDOUT);
+}
+
+int
urtwn_fw_loadpage(void *cookie, int page, uint8_t *buf, int len)
{
struct urtwn_softc *sc = cookie;
@@ -1707,7 +1940,9 @@ urtwn_load_firmware(void *cookie, u_char **fw, size_t *len)
const char *name;
int error;
- if (sc->sc_sc.chip & RTWN_CHIP_88E)
+ if (sc->sc_sc.chip & RTWN_CHIP_92E)
+ name = "urtwn-rtl8192eu_nic";
+ else if (sc->sc_sc.chip & RTWN_CHIP_88E)
name = "urtwn-rtl8188eufw";
else if ((sc->sc_sc.chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) ==
RTWN_CHIP_UMC_A_CUT)
@@ -1739,6 +1974,13 @@ urtwn_dma_init(void *cookie)
pagecnt = R88E_TX_PAGE_COUNT;
boundary = R88E_TX_PAGE_BOUNDARY;
dmasize = R88E_MAX_RX_DMA_SIZE;
+ } else if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ hqpages = R92E_HQ_NPAGES;
+ lqpages = R92E_LQ_NPAGES;
+ nqpages = R92E_NQ_NPAGES;
+ pagecnt = R92E_TX_PAGE_COUNT;
+ boundary = R92E_TX_PAGE_BOUNDARY;
+ dmasize = R92E_MAX_RX_DMA_SIZE;
} else {
hqpages = R92C_HQ_NPAGES;
lqpages = R92C_LQ_NPAGES;
@@ -1749,7 +1991,11 @@ urtwn_dma_init(void *cookie)
}
/* Initialize LLT table. */
- error = urtwn_llt_init(sc, pagecnt);
+ if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ error = urtwn_auto_llt_init(sc);
+ } else {
+ error = urtwn_llt_init(sc, pagecnt);
+ }
if (error != 0)
return (error);
@@ -1804,10 +2050,12 @@ urtwn_dma_init(void *cookie)
/* Set Tx/Rx transfer page boundary. */
urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, dmasize - 1);
- /* Set Tx/Rx transfer page size. */
- urtwn_write_1(sc, R92C_PBP,
- SM(R92C_PBP_PSRX, R92C_PBP_128) |
- SM(R92C_PBP_PSTX, R92C_PBP_128));
+ if (!(sc->sc_sc.chip & RTWN_CHIP_92E)) {
+ /* Set Tx/Rx transfer page size. */
+ urtwn_write_1(sc, R92C_PBP,
+ SM(R92C_PBP_PSRX, R92C_PBP_128) |
+ SM(R92C_PBP_PSTX, R92C_PBP_128));
+ }
return (error);
}
@@ -1824,6 +2072,11 @@ urtwn_mac_init(void *cookie)
rtl8188eu_mac[i].val);
}
urtwn_write_1(sc, R92C_MAX_AGGR_NUM, 0x07);
+ } else if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ for (i = 0; i < nitems(rtl8192eu_mac); i++) {
+ urtwn_write_1(sc, rtl8192eu_mac[i].reg,
+ rtl8192eu_mac[i].val);
+ }
} else {
for (i = 0; i < nitems(rtl8192cu_mac); i++)
urtwn_write_1(sc, rtl8192cu_mac[i].reg,
@@ -1846,7 +2099,7 @@ urtwn_bb_init(void *cookie)
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
- if (!(sc->sc_sc.chip & RTWN_CHIP_88E))
+ if (!(sc->sc_sc.chip & (RTWN_CHIP_88E | RTWN_CHIP_92E)))
urtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83);
urtwn_write_1(sc, R92C_RF_CTRL,
@@ -1855,7 +2108,7 @@ urtwn_bb_init(void *cookie)
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
- if (!(sc->sc_sc.chip & RTWN_CHIP_88E)) {
+ if (!(sc->sc_sc.chip & (RTWN_CHIP_88E | RTWN_CHIP_92E))) {
urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f);
urtwn_write_1(sc, 0x15, 0xe9);
urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
@@ -1864,6 +2117,8 @@ urtwn_bb_init(void *cookie)
/* Select BB programming based on board type. */
if (sc->sc_sc.chip & RTWN_CHIP_88E)
prog = &rtl8188eu_bb_prog;
+ else if (sc->sc_sc.chip & RTWN_CHIP_92E)
+ prog = &rtl8192eu_bb_prog;
else if (!(sc->sc_sc.chip & RTWN_CHIP_92C)) {
if (sc->sc_sc.board_type == R92C_BOARD_TYPE_MINICARD)
prog = &rtl8188ce_bb_prog;
@@ -1934,11 +2189,26 @@ urtwn_bb_init(void *cookie)
DELAY(1);
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
DELAY(1);
+ } else if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040022);
+ DELAY(1);
+ urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040020);
+ DELAY(1);
+ }
+ if (sc->sc_sc.chip & RTWN_CHIP_88E) {
xtal = sc->sc_sc.crystal_cap & 0x3f;
reg = urtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
urtwn_bb_write(sc, R92C_AFE_XTAL_CTRL,
RW(reg, R92C_AFE_XTAL_CTRL_ADDR, xtal | xtal << 6));
+ } else if (sc->sc_sc.chip & RTWN_CHIP_92E) {
+ xtal = sc->sc_sc.crystal_cap & 0x3f;
+ reg = urtwn_read_4(sc, R92C_AFE_CTRL3);
+ reg &= 0xff000fff;
+ reg |= (xtal | (xtal << 6)) << 12;
+ urtwn_write_4(sc, R92C_AFE_CTRL3, reg);
+
+ urtwn_write_4(sc, R92C_AFE_XTAL_CTRL, 0x000f81fb);
}
if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR)
@@ -1952,6 +2222,8 @@ urtwn_power_on(void *cookie)
if (sc->sc_sc.chip & RTWN_CHIP_88E)
return (urtwn_r88e_power_on(sc));
+ else if (sc->sc_sc.chip & RTWN_CHIP_92E)
+ return (urtwn_r92e_power_on(sc));
return (urtwn_r92c_power_on(sc));
}
@@ -1988,6 +2260,9 @@ urtwn_init(void *cookie)
struct urtwn_softc *sc = cookie;
int i, error;
+ if (sc->sc_sc.chip & RTWN_CHIP_92E)
+ urtwn_write_1(sc, R92C_ACLK_MON, 0);
+
/* Queue Rx xfers. */
for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
struct urtwn_rx_data *data = &sc->rx_data[i];