diff options
author | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2018-12-04 10:47:33 +0000 |
---|---|---|
committer | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2018-12-04 10:47:33 +0000 |
commit | 0cf530cb1e36e672c7a8cbef6f1b9b834e20c675 (patch) | |
tree | 93e1c9f8eb46d05134a4cbe18055e1a5335d0f99 /sys/dev | |
parent | 2975b01a5b89f23dc156323c95b38cbbbc45ffc0 (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.h | 424 | ||||
-rw-r--r-- | sys/dev/ic/rtwn.c | 575 | ||||
-rw-r--r-- | sys/dev/ic/rtwnvar.h | 4 | ||||
-rw-r--r-- | sys/dev/usb/if_urtwn.c | 397 |
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]; |