diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2015-05-04 11:46:30 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2015-05-04 11:46:30 +0000 |
commit | 3b0a556e43d0b6562e7a74e0732a171bed248b1b (patch) | |
tree | ffa692f9021d4874c05717c42d65a35df0314863 /sys | |
parent | 6405e9f5b91354a3992b23ec9813f57487908b7c (diff) |
Add support for RTL8188EU chips to urtwn(4).
Patch by Mikhail <mp39590@gmail.com>, based on FreeBSD r264912 by kevlo.
Tested with 8188EU (TP-Link TL-WN725N). No regression on 8188CUS.
There are performance problems with 8188EU devices, cause unknown.
These will hopefully be resolved soon.
ok mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/if_urtwn.c | 705 | ||||
-rw-r--r-- | sys/dev/usb/if_urtwnreg.h | 304 |
2 files changed, 892 insertions, 117 deletions
diff --git a/sys/dev/usb/if_urtwn.c b/sys/dev/usb/if_urtwn.c index 2196ad5b7ac..91f46fa0651 100644 --- a/sys/dev/usb/if_urtwn.c +++ b/sys/dev/usb/if_urtwn.c @@ -1,7 +1,8 @@ -/* $OpenBSD: if_urtwn.c,v 1.43 2015/03/14 03:38:49 jsg Exp $ */ +/* $OpenBSD: if_urtwn.c,v 1.44 2015/05/04 11:46:29 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> + * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +18,7 @@ */ /* - * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188RU/RTL8192CU. + * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU. */ #include "bpfilter.h" @@ -140,7 +141,10 @@ static const struct usb_devno urtwn_devs[] = { { USB_VENDOR_TPLINK, USB_PRODUCT_TPLINK_RTL8192CU }, { USB_VENDOR_TRENDNET, USB_PRODUCT_TRENDNET_RTL8188CU }, { USB_VENDOR_TRENDNET, USB_PRODUCT_TRENDNET_RTL8192CU }, - { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RTL8192CU } + { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RTL8192CU }, + /* URTWN_RTL8188E */ + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188ETV }, + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188EU } }; int urtwn_match(struct device *, void *, void *); @@ -167,14 +171,17 @@ uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t); uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t); uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t); int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int); -void urtwn_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t); +void urtwn_r92c_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t); +void urtwn_r88e_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t); uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t); void urtwn_cam_write(struct urtwn_softc *, uint32_t, uint32_t); int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t); uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t); void urtwn_efuse_read(struct urtwn_softc *); +void urtwn_efuse_switch_power(struct urtwn_softc *); int urtwn_read_chipid(struct urtwn_softc *); void urtwn_read_rom(struct urtwn_softc *); +void urtwn_r88e_read_rom(struct urtwn_softc *); int urtwn_media_change(struct ifnet *); int urtwn_ra_init(struct urtwn_softc *); void urtwn_tsf_sync_enable(struct urtwn_softc *); @@ -195,6 +202,7 @@ void urtwn_delete_key(struct ieee80211com *, void urtwn_delete_key_cb(struct urtwn_softc *, void *); void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t); int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *); +int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *); void urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int); void urtwn_rxeof(struct usbd_xfer *, void *, usbd_status); @@ -205,12 +213,15 @@ int urtwn_tx(struct urtwn_softc *, struct mbuf *, void urtwn_start(struct ifnet *); void urtwn_watchdog(struct ifnet *); int urtwn_ioctl(struct ifnet *, u_long, caddr_t); -int urtwn_power_on(struct urtwn_softc *); +int urtwn_r92c_power_on(struct urtwn_softc *); +int urtwn_r88e_power_on(struct urtwn_softc *); int urtwn_llt_init(struct urtwn_softc *); void urtwn_fw_reset(struct urtwn_softc *); +void urtwn_r88e_fw_reset(struct urtwn_softc *); int urtwn_fw_loadpage(struct urtwn_softc *, int, uint8_t *, int); int urtwn_load_firmware(struct urtwn_softc *); -int urtwn_dma_init(struct urtwn_softc *); +int urtwn_r92c_dma_init(struct urtwn_softc *); +int urtwn_r88e_dma_init(struct urtwn_softc *); void urtwn_mac_init(struct urtwn_softc *); void urtwn_bb_init(struct urtwn_softc *); void urtwn_rf_init(struct urtwn_softc *); @@ -222,6 +233,9 @@ void urtwn_write_txpower(struct urtwn_softc *, int, uint16_t[]); void urtwn_get_txpower(struct urtwn_softc *, int, struct ieee80211_channel *, struct ieee80211_channel *, uint16_t[]); +void urtwn_r88e_get_txpower(struct urtwn_softc *, int, + struct ieee80211_channel *, + struct ieee80211_channel *, uint16_t[]); void urtwn_set_txpower(struct urtwn_softc *, struct ieee80211_channel *, struct ieee80211_channel *); void urtwn_set_chan(struct urtwn_softc *, @@ -287,6 +301,10 @@ urtwn_attach(struct device *parent, struct device *self, void *aux) return; } + if (uaa->product == USB_PRODUCT_REALTEK_RTL8188EU || + uaa->product == USB_PRODUCT_REALTEK_RTL8188ETV) + sc->chip |= URTWN_CHIP_88E; + error = urtwn_read_chipid(sc); if (error != 0) { printf("%s: unsupported test chip\n", sc->sc_dev.dv_xname); @@ -301,11 +319,16 @@ urtwn_attach(struct device *parent, struct device *self, void *aux) sc->ntxchains = 1; sc->nrxchains = 1; } - urtwn_read_rom(sc); + + if (sc->chip & URTWN_CHIP_88E) + urtwn_r88e_read_rom(sc); + else + urtwn_read_rom(sc); printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n", sc->sc_dev.dv_xname, (sc->chip & URTWN_CHIP_92C) ? "8192CU" : + (sc->chip & URTWN_CHIP_88E) ? "8188EU" : (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" : (sc->board_type == R92C_BOARD_TYPE_MINICARD) ? "8188CE-VAU" : "8188CUS", sc->ntxchains, sc->nrxchains, @@ -752,14 +775,31 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uint8_t id, const void *buf, int len) return (0); } -void +__inline void urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val) { + + sc->sc_rf_write(sc, chain, addr, val); +} + +void +urtwn_r92c_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, + uint32_t val) +{ urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), SM(R92C_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); } +void +urtwn_r88e_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, +uint32_t val) +{ + urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), + SM(R88E_LSSI_PARAM_ADDR, addr) | + SM(R92C_LSSI_PARAM_DATA, val)); +} + uint32_t urtwn_rf_read(struct urtwn_softc *sc, int chain, uint8_t addr) { @@ -848,22 +888,8 @@ urtwn_efuse_read(struct urtwn_softc *sc) uint8_t off, msk; int i; - reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL); - if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { - urtwn_write_2(sc, R92C_SYS_ISO_CTRL, - reg | R92C_SYS_ISO_CTRL_PWC_EV12V); - } - reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); - if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { - urtwn_write_2(sc, R92C_SYS_FUNC_EN, - reg | R92C_SYS_FUNC_EN_ELDR); - } - reg = urtwn_read_2(sc, R92C_SYS_CLKR); - if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != - (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { - urtwn_write_2(sc, R92C_SYS_CLKR, - reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); - } + urtwn_efuse_switch_power(sc); + memset(&sc->rom, 0xff, sizeof(sc->rom)); while (addr < 512) { reg = urtwn_efuse_read_1(sc, addr); @@ -894,11 +920,37 @@ urtwn_efuse_read(struct urtwn_softc *sc) #endif } +void +urtwn_efuse_switch_power(struct urtwn_softc *sc) +{ + uint32_t reg; + + reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL); + if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { + urtwn_write_2(sc, R92C_SYS_ISO_CTRL, + reg | R92C_SYS_ISO_CTRL_PWC_EV12V); + } + reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); + if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { + urtwn_write_2(sc, R92C_SYS_FUNC_EN, + reg | R92C_SYS_FUNC_EN_ELDR); + } + reg = urtwn_read_2(sc, R92C_SYS_CLKR); + if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != + (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { + urtwn_write_2(sc, R92C_SYS_CLKR, + reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); + } +} + int urtwn_read_chipid(struct urtwn_softc *sc) { uint32_t reg; + if (sc->chip & URTWN_CHIP_88E) + return (0); + reg = urtwn_read_4(sc, R92C_SYS_CFG); if (reg & R92C_SYS_CFG_TRP_VAUX_EN) return (EIO); @@ -936,8 +988,71 @@ urtwn_read_rom(struct urtwn_softc *sc) sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY); DPRINTF(("regulatory type=%d\n", sc->regulatory)); - IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr); + + sc->sc_rf_write = urtwn_r92c_rf_write; + sc->sc_power_on = urtwn_r92c_power_on; + sc->sc_dma_init = urtwn_r92c_dma_init; +} + +void +urtwn_r88e_read_rom(struct urtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint8_t *rom = sc->r88e_rom; + uint16_t addr = 0; + uint32_t reg; + uint8_t off, msk, tmp; + int i; + + off = 0; + urtwn_efuse_switch_power(sc); + + /* Read full ROM image. */ + memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom)); + while (addr < 1024) { + reg = urtwn_efuse_read_1(sc, addr); + if (reg == 0xff) + break; + addr++; + if ((reg & 0x1f) == 0x0f) { + tmp = (reg & 0xe0) >> 5; + reg = urtwn_efuse_read_1(sc, addr); + if ((reg & 0x0f) != 0x0f) + off = ((reg & 0xf0) >> 1) | tmp; + addr++; + } else + off = reg >> 4; + msk = reg & 0xf; + for (i = 0; i < 4; i++) { + if (msk & (1 << i)) + continue; + rom[off * 8 + i * 2 + 0] = + urtwn_efuse_read_1(sc, addr); + addr++; + rom[off * 8 + i * 2 + 1] = + urtwn_efuse_read_1(sc, addr); + addr++; + } + } + + addr = 0x10; + for (i = 0; i < 6; i++) + sc->cck_tx_pwr[i] = sc->r88e_rom[addr++]; + for (i = 0; i < 5; i++) + sc->ht40_tx_pwr[i] = sc->r88e_rom[addr++]; + sc->bw20_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf0) >> 4; + if (sc->bw20_tx_pwr_diff & 0x08) + sc->bw20_tx_pwr_diff |= 0xf0; + sc->ofdm_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf); + if (sc->ofdm_tx_pwr_diff & 0x08) + sc->ofdm_tx_pwr_diff |= 0xf0; + sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY); + IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->r88e_rom[0xd7]); + + sc->sc_rf_write = urtwn_r88e_rf_write; + sc->sc_power_on = urtwn_r88e_power_on; + sc->sc_dma_init = urtwn_r88e_dma_init; } int @@ -1063,11 +1178,24 @@ urtwn_set_led(struct urtwn_softc *sc, int led, int on) uint8_t reg; if (led == URTWN_LED_LINK) { - reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70; - if (!on) - reg |= R92C_LEDCFG0_DIS; - urtwn_write_1(sc, R92C_LEDCFG0, reg); - sc->ledlink = on; /* Save LED state. */ + if (sc->chip & URTWN_CHIP_88E) { + reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; + urtwn_write_1(sc, R92C_LEDCFG2, reg | 0x60); + if (!on) { + reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0x90; + urtwn_write_1(sc, R92C_LEDCFG2, + reg | R92C_LEDCFG0_DIS); + urtwn_write_1(sc, R92C_MAC_PINMUX_CFG, + urtwn_read_1(sc, R92C_MAC_PINMUX_CFG) & + 0xfe); + } + } else { + reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70; + if (!on) + reg |= R92C_LEDCFG0_DIS; + urtwn_write_1(sc, R92C_LEDCFG0, reg); + } + sc->ledlink = on; /* Save LED state. */ } } @@ -1202,9 +1330,11 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); - reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); - urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); + if (!(sc->chip & URTWN_CHIP_88E)) { + reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); + reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); + urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); + } } /* Make link LED blink during scan. */ @@ -1225,9 +1355,11 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); - reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); - urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); + if (!(sc->chip & URTWN_CHIP_88E)) { + reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); + reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); + urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); + } urtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL); break; @@ -1285,7 +1417,10 @@ urtwn_newstate_cb(struct urtwn_softc *sc, void *arg) urtwn_write_1(sc, R92C_T2T_SIFS + 1, 10); /* Intialize rate adaptation. */ - urtwn_ra_init(sc); + if (sc->chip & URTWN_CHIP_88E) + ni->ni_txrate = ni->ni_rates.rs_nrates-1; + else + urtwn_ra_init(sc); /* Turn link LED on. */ urtwn_set_led(sc, URTWN_LED_LINK, 1); @@ -1456,19 +1591,21 @@ urtwn_update_avgrssi(struct urtwn_softc *sc, int rate, int8_t rssi) pwdb = 100; else pwdb = 100 + rssi; - if (rate <= 3) { - /* CCK gain is smaller than OFDM/MCS gain. */ - pwdb += 6; - if (pwdb > 100) - pwdb = 100; - if (pwdb <= 14) - pwdb -= 4; - else if (pwdb <= 26) - pwdb -= 8; - else if (pwdb <= 34) - pwdb -= 6; - else if (pwdb <= 42) - pwdb -= 2; + if (!(sc->chip & URTWN_CHIP_88E)) { + if (rate <= 3) { + /* CCK gain is smaller than OFDM/MCS gain. */ + pwdb += 6; + if (pwdb > 100) + pwdb = 100; + if (pwdb <= 14) + pwdb -= 4; + else if (pwdb <= 26) + pwdb -= 8; + else if (pwdb <= 34) + pwdb -= 6; + else if (pwdb <= 42) + pwdb -= 2; + } } if (sc->avg_pwdb == -1) /* Init. */ sc->avg_pwdb = pwdb; @@ -1505,6 +1642,57 @@ urtwn_get_rssi(struct urtwn_softc *sc, int rate, void *physt) return (rssi); } +int8_t +urtwn_r88e_get_rssi(struct urtwn_softc *sc, int rate, void *physt) +{ + struct r92c_rx_phystat *phy; + struct r88e_rx_cck *cck; + uint8_t cck_agc_rpt, lna_idx, vga_idx; + int8_t rssi; + + rssi = 0; + if (rate <= 3) { + cck = (struct r88e_rx_cck *)physt; + cck_agc_rpt = cck->agc_rpt; + lna_idx = (cck_agc_rpt & 0xe0) >> 5; + vga_idx = cck_agc_rpt & 0x1f; + switch (lna_idx) { + case 7: + if (vga_idx <= 27) + rssi = -100 + 2* (27 - vga_idx); + else + rssi = -100; + break; + case 6: + rssi = -48 + 2 * (2 - vga_idx); + break; + case 5: + rssi = -42 + 2 * (7 - vga_idx); + break; + case 4: + rssi = -36 + 2 * (7 - vga_idx); + break; + case 3: + rssi = -24 + 2 * (7 - vga_idx); + break; + case 2: + rssi = -12 + 2 * (5 - vga_idx); + break; + case 1: + rssi = 8 - (2 * vga_idx); + break; + case 0: + rssi = 14 - (2 * vga_idx); + break; + } + rssi += 6; + } else { /* OFDM/HT. */ + phy = (struct r92c_rx_phystat *)physt; + rssi = ((le32toh(phy->phydw1) >> 1) & 0x7f) - 110; + } + return (rssi); +} + void urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen) { @@ -1542,7 +1730,10 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen) /* Get RSSI from PHY status descriptor if present. */ if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { - rssi = urtwn_get_rssi(sc, rate, &stat[1]); + if (sc->chip & URTWN_CHIP_88E) + rssi = urtwn_r88e_get_rssi(sc, rate, &stat[1]); + else + rssi = urtwn_get_rssi(sc, rate, &stat[1]); /* Update our average RSSI. */ urtwn_update_avgrssi(sc, rate, rssi); } @@ -1794,11 +1985,18 @@ urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) raid = R92C_RAID_11B; else raid = R92C_RAID_11BG; - txd->txdw1 |= htole32( - SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | - SM(R92C_TXDW1_RAID, raid) | - R92C_TXDW1_AGGBK); + if (sc->chip & URTWN_CHIP_88E) { + txd->txdw1 |= htole32( + SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) | + SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | + SM(R92C_TXDW1_RAID, raid)); + txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); + } else { + txd->txdw1 |= htole32( + SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) | + SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | + SM(R92C_TXDW1_RAID, raid) | R92C_TXDW1_AGGBK); + } if (ic->ic_flags & IEEE80211_F_USEPROT) { if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { @@ -2018,9 +2216,16 @@ urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (error); } -int +__inline int urtwn_power_on(struct urtwn_softc *sc) { + + return sc->sc_power_on(sc); +} + +int +urtwn_r92c_power_on(struct urtwn_softc *sc) +{ uint32_t reg; int ntries; @@ -2104,12 +2309,73 @@ urtwn_power_on(struct urtwn_softc *sc) } int +urtwn_r88e_power_on(struct urtwn_softc *sc) +{ + uint8_t val; + uint32_t reg; + int ntries; + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + val = urtwn_read_1(sc, 0x6) & 0x2; + if (val == 0x2) + break; + DELAY(10); + } + if (ntries == 5000) { + printf("%s: timeout waiting for chip power up\n", + sc->sc_dev.dv_xname); + return (ETIMEDOUT); + } + + /* Reset BB. */ + urtwn_write_1(sc, R92C_SYS_FUNC_EN, + urtwn_read_1(sc, R92C_SYS_FUNC_EN) & ~(R92C_SYS_FUNC_EN_BBRSTB | + R92C_SYS_FUNC_EN_BB_GLB_RST)); + + urtwn_write_1(sc, 0x26, urtwn_read_1(sc, 0x26) | 0x80); + + /* Disable HWPDN. */ + urtwn_write_1(sc, 0x5, urtwn_read_1(sc, 0x5) & ~0x80); + + /* Disable WL suspend. */ + urtwn_write_1(sc, 0x5, urtwn_read_1(sc, 0x5) & ~0x18); + + urtwn_write_1(sc, 0x5, urtwn_read_1(sc, 0x5) | 0x1); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(urtwn_read_1(sc, 0x5) & 0x1)) + break; + DELAY(10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable LDO normal mode. */ + urtwn_write_1(sc, 0x23, urtwn_read_1(sc, 0x23) & ~0x10); + + /* 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_llt_init(struct urtwn_softc *sc) { - int i, error; + int i, error, page_count, pktbuf_count; - /* Reserve pages [0; R92C_TX_PAGE_COUNT]. */ - for (i = 0; i < R92C_TX_PAGE_COUNT; i++) { + page_count = (sc->chip & URTWN_CHIP_88E) ? + R88E_TX_PAGE_COUNT : R92C_TX_PAGE_COUNT; + pktbuf_count = (sc->chip & URTWN_CHIP_88E) ? + R88E_TXPKTBUF_COUNT : R92C_TXPKTBUF_COUNT; + + /* Reserve pages [0; page_count]. */ + for (i = 0; i < page_count; i++) { if ((error = urtwn_llt_write(sc, i, i + 1)) != 0) return (error); } @@ -2117,15 +2383,15 @@ urtwn_llt_init(struct urtwn_softc *sc) if ((error = urtwn_llt_write(sc, i, 0xff)) != 0) return (error); /* - * Use pages [R92C_TX_PAGE_COUNT + 1; R92C_TXPKTBUF_COUNT - 1] + * Use pages [page_count + 1; pktbuf_count - 1] * as ring buffer. */ - for (++i; i < R92C_TXPKTBUF_COUNT - 1; i++) { + for (++i; i < pktbuf_count - 1; i++) { if ((error = urtwn_llt_write(sc, i, i + 1)) != 0) return (error); } /* Make the last page point to the beginning of the ring buffer. */ - error = urtwn_llt_write(sc, i, R92C_TX_PAGE_COUNT + 1); + error = urtwn_llt_write(sc, i, page_count + 1); return (error); } @@ -2147,6 +2413,20 @@ urtwn_fw_reset(struct urtwn_softc *sc) } /* Force 8051 reset. */ urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); + urtwn_write_2(sc, R92C_SYS_FUNC_EN, + urtwn_read_2(sc, R92C_SYS_FUNC_EN) | + R92C_SYS_FUNC_EN_CPUEN); +} + + +void +urtwn_r88e_fw_reset(struct urtwn_softc *sc) +{ + uint16_t reg; + + reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); + urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); + urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); } int @@ -2188,8 +2468,10 @@ urtwn_load_firmware(struct urtwn_softc *sc) int mlen, ntries, page, error; /* Read firmware image from the filesystem. */ - if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == - URTWN_CHIP_UMC_A_CUT) + if (sc->chip & URTWN_CHIP_88E) + name = "urtwn-rtl8188eufw"; + else if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == + URTWN_CHIP_UMC_A_CUT) name = "urtwn-rtl8192cfwU"; else name = "urtwn-rtl8192cfwT"; @@ -2207,6 +2489,7 @@ urtwn_load_firmware(struct urtwn_softc *sc) hdr = (const struct r92c_fw_hdr *)ptr; /* Check if there is a valid FW header and skip it. */ if ((letoh16(hdr->signature) >> 4) == 0x88c || + (le16toh(hdr->signature) >> 4) == 0x88e || (letoh16(hdr->signature) >> 4) == 0x92c) { DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n", letoh16(hdr->version), letoh16(hdr->subversion), @@ -2215,13 +2498,14 @@ urtwn_load_firmware(struct urtwn_softc *sc) len -= sizeof(*hdr); } - if (urtwn_read_1(sc, R92C_MCUFWDL) & 0x80) { - urtwn_fw_reset(sc); + if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) { + if (sc->chip & URTWN_CHIP_88E) + urtwn_r88e_fw_reset(sc); + else + urtwn_fw_reset(sc); urtwn_write_1(sc, R92C_MCUFWDL, 0); } - urtwn_write_2(sc, R92C_SYS_FUNC_EN, - urtwn_read_2(sc, R92C_SYS_FUNC_EN) | - R92C_SYS_FUNC_EN_CPUEN); + urtwn_write_1(sc, R92C_MCUFWDL, urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN); urtwn_write_1(sc, R92C_MCUFWDL + 2, @@ -2262,6 +2546,8 @@ urtwn_load_firmware(struct urtwn_softc *sc) reg = urtwn_read_4(sc, R92C_MCUFWDL); reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY; urtwn_write_4(sc, R92C_MCUFWDL, reg); + if (sc->chip & URTWN_CHIP_88E) + urtwn_r88e_fw_reset(sc); /* Wait for firmware readiness. */ for (ntries = 0; ntries < 1000; ntries++) { if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) @@ -2279,9 +2565,16 @@ urtwn_load_firmware(struct urtwn_softc *sc) return (error); } -int +__inline int urtwn_dma_init(struct urtwn_softc *sc) { + + return sc->sc_dma_init(sc); +} + +int +urtwn_r92c_dma_init(struct urtwn_softc *sc) +{ int hashq, hasnq, haslq, nqueues, nqpages, nrempages; uint32_t reg; int error; @@ -2359,14 +2652,77 @@ urtwn_dma_init(struct urtwn_softc *sc) return (0); } +int +urtwn_r88e_dma_init(struct urtwn_softc *sc) +{ + usb_interface_descriptor_t *id; + uint32_t reg; + int nrempages, nqpages, nqueues = 1; + int error; + + /* Initialize LLT table. */ + error = urtwn_llt_init(sc); + if (error != 0) + return (error); + + /* Get Tx queues to USB endpoints mapping. */ + id = usbd_get_interface_descriptor(sc->sc_iface); + nqueues = id->bNumEndpoints - 1; + + /* Get the number of pages for each queue. */ + nqpages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) / nqueues; + /* The remaining pages are assigned to the high priority queue. */ + nrempages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) % nqueues; + + /* Set number of pages for normal priority queue. */ + urtwn_write_2(sc, R92C_RQPN_NPQ, 0x000d); + urtwn_write_4(sc, R92C_RQPN, 0x808e000d); + + urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R88E_TX_PAGE_BOUNDARY); + urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R88E_TX_PAGE_BOUNDARY); + urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R88E_TX_PAGE_BOUNDARY); + urtwn_write_1(sc, R92C_TRXFF_BNDY, R88E_TX_PAGE_BOUNDARY); + urtwn_write_1(sc, R92C_TDECTRL + 1, R88E_TX_PAGE_BOUNDARY); + + /* Set queue to USB pipe mapping. */ + reg = urtwn_read_2(sc, R92C_TRXDMA_CTRL); + reg &= ~R92C_TRXDMA_CTRL_QMAP_M; + if (nqueues == 1) + reg |= R92C_TRXDMA_CTRL_QMAP_LQ; + else if (nqueues == 2) + reg |= R92C_TRXDMA_CTRL_QMAP_HQ_NQ; + else + reg |= R92C_TRXDMA_CTRL_QMAP_3EP; + urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + + /* Set Tx/Rx transfer page boundary. */ + urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x23ff); + + /* 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 (0); +} + void urtwn_mac_init(struct urtwn_softc *sc) { int i; /* Write MAC initialization values. */ - for (i = 0; i < nitems(rtl8192cu_mac); i++) - urtwn_write_1(sc, rtl8192cu_mac[i].reg, rtl8192cu_mac[i].val); + if (sc->chip & URTWN_CHIP_88E) { + for (i = 0; i < nitems(rtl8188eu_mac); i++) { + urtwn_write_1(sc, rtl8188eu_mac[i].reg, + rtl8188eu_mac[i].val); + } + urtwn_write_1(sc, R92C_MAX_AGGR_NUM, 0x07); + } else { + for (i = 0; i < nitems(rtl8192cu_mac); i++) + urtwn_write_1(sc, rtl8192cu_mac[i].reg, + rtl8192cu_mac[i].val); + } } void @@ -2374,6 +2730,7 @@ urtwn_bb_init(struct urtwn_softc *sc) { const struct urtwn_bb_prog *prog; uint32_t reg; + uint8_t crystalcap; int i; /* Enable BB and RF. */ @@ -2382,7 +2739,8 @@ urtwn_bb_init(struct urtwn_softc *sc) R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_DIO_RF); - urtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); + if (!(sc->chip & URTWN_CHIP_88E)) + urtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); urtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); @@ -2390,12 +2748,16 @@ urtwn_bb_init(struct urtwn_softc *sc) R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); - urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); - urtwn_write_1(sc, 0x15, 0xe9); - urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); + if (!(sc->chip & URTWN_CHIP_88E)) { + urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); + urtwn_write_1(sc, 0x15, 0xe9); + urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); + } /* Select BB programming based on board type. */ - if (!(sc->chip & URTWN_CHIP_92C)) { + if (sc->chip & URTWN_CHIP_88E) + prog = &rtl8188eu_bb_prog; + else if (!(sc->chip & URTWN_CHIP_92C)) { if (sc->board_type == R92C_BOARD_TYPE_MINICARD) prog = &rtl8188ce_bb_prog; else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) @@ -2460,9 +2822,25 @@ urtwn_bb_init(struct urtwn_softc *sc) DELAY(1); } - if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & - R92C_HSSI_PARAM2_CCK_HIPWR) - sc->sc_flags |= URTWN_FLAG_CCK_HIPWR; + if (sc->chip & URTWN_CHIP_88E) { + urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); + DELAY(1); + urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420); + DELAY(1); + + crystalcap = sc->r88e_rom[0xb9]; + if (crystalcap == 0xff) + crystalcap = 0x20; + crystalcap &= 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, + crystalcap | crystalcap << 6)); + } else { + if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & + R92C_HSSI_PARAM2_CCK_HIPWR) + sc->sc_flags |= URTWN_FLAG_CCK_HIPWR; + } } void @@ -2473,7 +2851,9 @@ urtwn_rf_init(struct urtwn_softc *sc) int i, j, idx, off; /* Select RF programming based on board type. */ - if (!(sc->chip & URTWN_CHIP_92C)) { + if (sc->chip & URTWN_CHIP_88E) + prog = rtl8188eu_rf_prog; + else if (!(sc->chip & URTWN_CHIP_92C)) { if (sc->board_type == R92C_BOARD_TYPE_MINICARD) prog = rtl8188ce_rf_prog; else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) @@ -2764,6 +3144,75 @@ urtwn_get_txpower(struct urtwn_softc *sc, int chain, } void +urtwn_r88e_get_txpower(struct urtwn_softc *sc, int chain, + struct ieee80211_channel *c, struct ieee80211_channel *extc, + uint16_t power[URTWN_RIDX_COUNT]) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint16_t cckpow, ofdmpow, bw20pow, htpow; + const struct urtwn_r88e_txpwr *base; + 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 if (chan <= 13) + group = 4; + else + group = 5; + + /* Get original Tx power based on board type and RF chain. */ + base = &rtl8188eu_txagc[chain]; + + memset(power, 0, URTWN_RIDX_COUNT * sizeof(power[0])); + if (sc->regulatory == 0) { + for (ridx = 0; ridx <= 3; ridx++) + power[ridx] = base->pwr[0][ridx]; + } + for (ridx = 4; ridx < URTWN_RIDX_COUNT; ridx++) { + if (sc->regulatory == 3) + power[ridx] = base->pwr[0][ridx]; + else if (sc->regulatory == 1) { + if (extc == NULL) + power[ridx] = base->pwr[group][ridx]; + } else if (sc->regulatory != 2) + power[ridx] = base->pwr[0][ridx]; + } + + /* Compute per-CCK rate Tx power. */ + cckpow = sc->cck_tx_pwr[group]; + for (ridx = 0; ridx <= 3; ridx++) { + power[ridx] += cckpow; + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } + + htpow = sc->ht40_tx_pwr[group]; + + /* Compute per-OFDM rate Tx power. */ + ofdmpow = htpow + sc->ofdm_tx_pwr_diff; + for (ridx = 4; ridx <= 11; ridx++) { + power[ridx] += ofdmpow; + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } + + bw20pow = htpow + sc->bw20_tx_pwr_diff; + for (ridx = 12; ridx <= 27; ridx++) { + power[ridx] += bw20pow; + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } +} + +void urtwn_set_txpower(struct urtwn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { @@ -2772,7 +3221,10 @@ urtwn_set_txpower(struct urtwn_softc *sc, struct ieee80211_channel *c, for (i = 0; i < sc->ntxchains; i++) { /* Compute per-rate Tx power values. */ - urtwn_get_txpower(sc, i, c, extc, power); + if (sc->chip & URTWN_CHIP_88E) + urtwn_r88e_get_txpower(sc, i, c, extc, power); + else + urtwn_get_txpower(sc, i, c, extc, power); /* Write per-rate Tx power values to hardware. */ urtwn_write_txpower(sc, i, power); } @@ -2845,13 +3297,17 @@ urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, urtwn_bb_write(sc, R92C_FPGA1_RFMOD, urtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ); - urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, - urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | - R92C_FPGA0_ANAPARAM2_CBW20); + if (!(sc->chip & URTWN_CHIP_88E)) { + urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, + urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | + R92C_FPGA0_ANAPARAM2_CBW20); + } /* Select 20MHz bandwidth. */ urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | R92C_RF_CHNLBW_BW20 | chan); + (sc->rf_chnlbw[0] & ~0xfff) | chan | + ((sc->chip & URTWN_CHIP_88E) ? R88E_RF_CHNLBW_BW20 : + R92C_RF_CHNLBW_BW20)); } } @@ -3026,6 +3482,7 @@ urtwn_init(struct ifnet *ifp) sc->sc_dev.dv_xname); goto fail; } + /* Power on adapter. */ error = urtwn_power_on(sc); if (error != 0) @@ -3040,8 +3497,19 @@ urtwn_init(struct ifnet *ifp) urtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4); /* Init interrupts. */ - urtwn_write_4(sc, R92C_HISR, 0xffffffff); - urtwn_write_4(sc, R92C_HIMR, 0xffffffff); + if (sc->chip & URTWN_CHIP_88E) { + urtwn_write_4(sc, R88E_HISR, 0xffffffff); + urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | + R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT); + urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | + R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR); + urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, + urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | + R92C_USB_SPECIAL_OPTION_INT_BULK_SEL); + } else { + urtwn_write_4(sc, R92C_HISR, 0xffffffff); + urtwn_write_4(sc, R92C_HIMR, 0xffffffff); + } /* Set MAC address. */ IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); @@ -3067,10 +3535,12 @@ urtwn_init(struct ifnet *ifp) urtwn_edca_init(sc); /* Setup rate fallback. */ - urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000); - urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404); - urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201); - urtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605); + if (!(sc->chip & URTWN_CHIP_88E)) { + urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000); + urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404); + urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201); + urtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605); + } urtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, urtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) | @@ -3085,27 +3555,33 @@ urtwn_init(struct ifnet *ifp) urtwn_write_1(sc, R92C_TRXDMA_CTRL, urtwn_read_1(sc, R92C_TRXDMA_CTRL) | R92C_TRXDMA_CTRL_RXDMA_AGG_EN); - urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, - urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | - R92C_USB_SPECIAL_OPTION_AGG_EN); urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); - urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); - urtwn_write_1(sc, R92C_USB_AGG_TH, 8); - urtwn_write_1(sc, R92C_USB_AGG_TO, 6); + if (sc->chip & URTWN_CHIP_88E) + urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4); + else { + urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); + urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, + urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | + R92C_USB_SPECIAL_OPTION_AGG_EN); + urtwn_write_1(sc, R92C_USB_AGG_TH, 8); + urtwn_write_1(sc, R92C_USB_AGG_TO, 6); + } /* Initialize beacon parameters. */ + urtwn_write_2(sc, R92C_BCN_CTRL, 0x1010); urtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); urtwn_write_1(sc, R92C_DRVERLYINT, 0x05); urtwn_write_1(sc, R92C_BCNDMATIM, 0x02); urtwn_write_2(sc, R92C_BCNTCFG, 0x660f); - /* Setup AMPDU aggregation. */ - urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ - urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); - urtwn_write_2(sc, 0x4ca, 0x0708); + if (!(sc->chip & URTWN_CHIP_88E)) { + /* Setup AMPDU aggregation. */ + urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ + urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); + urtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708); - urtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); - urtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0); + urtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); + } /* Load 8051 microcode. */ error = urtwn_load_firmware(sc); @@ -3117,6 +3593,12 @@ urtwn_init(struct ifnet *ifp) urtwn_bb_init(sc); urtwn_rf_init(sc); + if (sc->chip & URTWN_CHIP_88E) { + urtwn_write_2(sc, R92C_CR, + urtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN | + R92C_CR_MACRXEN); + } + /* Turn CCK and OFDM blocks on. */ reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); reg |= R92C_RFMOD_CCK_EN; @@ -3137,18 +3619,21 @@ urtwn_init(struct ifnet *ifp) urtwn_lc_calib(sc); /* Fix USB interference issue. */ - urtwn_write_1(sc, 0xfe40, 0xe0); - urtwn_write_1(sc, 0xfe41, 0x8d); - urtwn_write_1(sc, 0xfe42, 0x80); + if (!(sc->chip & URTWN_CHIP_88E)) { + urtwn_write_1(sc, 0xfe40, 0xe0); + urtwn_write_1(sc, 0xfe41, 0x8d); + urtwn_write_1(sc, 0xfe42, 0x80); - urtwn_pa_bias_init(sc); + urtwn_pa_bias_init(sc); + } /* Initialize GPIO setting. */ urtwn_write_1(sc, R92C_GPIO_MUXCFG, urtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT); /* Fix for lower temperature. */ - urtwn_write_1(sc, 0x15, 0xe9); + if (!(sc->chip & URTWN_CHIP_88E)) + urtwn_write_1(sc, 0x15, 0xe9); /* Set default channel. */ ic->ic_bss->ni_chan = ic->ic_ibss_chan; diff --git a/sys/dev/usb/if_urtwnreg.h b/sys/dev/usb/if_urtwnreg.h index 91c4f1bca85..edbad3d898c 100644 --- a/sys/dev/usb/if_urtwnreg.h +++ b/sys/dev/usb/if_urtwnreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_urtwnreg.h,v 1.4 2013/04/15 09:23:01 mglocker Exp $ */ +/* $OpenBSD: if_urtwnreg.h,v 1.5 2015/05/04 11:46:29 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -27,6 +27,9 @@ #define R92C_TXPKTBUF_COUNT 256 #define R92C_TX_PAGE_COUNT 248 #define R92C_TX_PAGE_BOUNDARY (R92C_TX_PAGE_COUNT + 1) +#define R88E_TXPKTBUF_COUNT 177 +#define R88E_TX_PAGE_COUNT 169 +#define R88E_TX_PAGE_BOUNDARY (R88E_TX_PAGE_COUNT + 1) #define R92C_H2C_NBOX 4 @@ -72,6 +75,11 @@ #define R92C_HSISR 0x05c #define R92C_MCUFWDL 0x080 #define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2) +#define R88E_HIMR 0x0b0 +#define R88E_HISR 0x0b4 +#define R88E_HIMRE 0x0b8 +#define R88E_HISRE 0x0bc +#define R92C_EFUSE_ACCESS 0x0cf #define R92C_BIST_SCAN 0x0d0 #define R92C_BIST_RPT 0x0d4 #define R92C_BIST_ROM_RPT 0x0d8 @@ -112,6 +120,7 @@ #define R92C_LLT_INIT 0x1e0 #define R92C_BB_ACCESS_CTRL 0x1e8 #define R92C_BB_ACCESS_DATA 0x1ec +#define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4) /* Tx DMA Configuration. */ #define R92C_RQPN 0x200 #define R92C_FIFOPAGE 0x204 @@ -141,6 +150,7 @@ #define R92C_RD_RESP_PKT_TH 0x463 #define R92C_INIRTS_RATE_SEL 0x480 #define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid)) +#define R92C_MAX_AGGR_NUM 0x4ca /* EDCA Configuration. */ #define R92C_EDCA_VO_PARAM 0x500 #define R92C_EDCA_VI_PARAM 0x504 @@ -286,6 +296,10 @@ /* Bits for R92C_LDOV12D_CTRL. */ #define R92C_LDOV12D_CTRL_LDV12_EN 0x01 +/* Bits for R92C_AFE_XTAL_CTRL. */ +#define R92C_AFE_XTAL_CTRL_ADDR_M 0x007ff800 +#define R92C_AFE_XTAL_CTRL_ADDR_S 11 + /* Bits for R92C_EFUSE_CTRL. */ #define R92C_EFUSE_CTRL_DATA_M 0x000000ff #define R92C_EFUSE_CTRL_DATA_S 0 @@ -307,10 +321,27 @@ #define R92C_MCUFWDL_BBINI_RDY 0x00000010 #define R92C_MCUFWDL_RFINI_RDY 0x00000020 #define R92C_MCUFWDL_WINTINI_RDY 0x00000040 +#define R92C_MCUFWDL_RAM_DL_SEL 0x00000080 #define R92C_MCUFWDL_PAGE_M 0x00070000 #define R92C_MCUFWDL_PAGE_S 16 #define R92C_MCUFWDL_CPRST 0x00800000 +/* Bits for R88E_HIMR. */ +#define R88E_HIMR_CPWM 0x00000100 +#define R88E_HIMR_CPWM2 0x00000200 +#define R88E_HIMR_TBDER 0x04000000 +#define R88E_HIMR_PSTIMEOUT 0x20000000 + +/* Bits for R88E_HIMRE.*/ +#define R88E_HIMRE_RXFOVW 0x00000100 +#define R88E_HIMRE_TXFOVW 0x00000200 +#define R88E_HIMRE_RXERR 0x00000400 +#define R88E_HIMRE_TXERR 0x00000800 + +/* Bits for R92C_EFUSE_ACCESS. */ +#define R92C_EFUSE_ACCESS_OFF 0x00 +#define R92C_EFUSE_ACCESS_ON 0x69 + /* Bits for R92C_HPON_FSM. */ #define R92C_HPON_FSM_CHIP_BONDING_ID_S 22 #define R92C_HPON_FSM_CHIP_BONDING_ID_M 0x00c00000 @@ -349,6 +380,7 @@ #define R92C_CR_MACTXEN 0x00000040 #define R92C_CR_MACRXEN 0x00000080 #define R92C_CR_ENSEC 0x00000200 +#define R92C_CR_CALTMR_EN 0x00000400 #define R92C_CR_NETTYPE_S 16 #define R92C_CR_NETTYPE_M 0x00030000 #define R92C_CR_NETTYPE_NOLINK 0 @@ -635,6 +667,8 @@ #define R92C_LSSI_PARAM_DATA_S 0 #define R92C_LSSI_PARAM_ADDR_M 0x03f00000 #define R92C_LSSI_PARAM_ADDR_S 20 +#define R88E_LSSI_PARAM_ADDR_M 0x0ff00000 +#define R88E_LSSI_PARAM_ADDR_S 20 /* Bits for R92C_FPGA0_ANAPARAM2. */ #define R92C_FPGA0_ANAPARAM2_CBW20 0x00000400 @@ -667,7 +701,8 @@ #define R92C_USB_STRING 0xfe80 /* Bits for R92C_USB_SPECIAL_OPTION. */ -#define R92C_USB_SPECIAL_OPTION_AGG_EN 0x08 +#define R92C_USB_SPECIAL_OPTION_AGG_EN 0x08 +#define R92C_USB_SPECIAL_OPTION_INT_BULK_SEL 0x10 /* Bits for R92C_USB_EP. */ #define R92C_USB_EP_HQ_M 0x000f @@ -725,6 +760,7 @@ #define R92C_RF_CHNLBW_CHNL_M 0x003ff #define R92C_RF_CHNLBW_CHNL_S 0 #define R92C_RF_CHNLBW_BW20 0x00400 +#define R88E_RF_CHNLBW_BW20 0x00c00 #define R92C_RF_CHNLBW_LCSTART 0x08000 @@ -935,6 +971,26 @@ struct r92c_rx_cck { uint8_t agc_rpt; } __packed; +struct r88e_rx_cck { + uint8_t path_agc[2]; + uint8_t sig_qual; + uint8_t agc_rpt; + uint8_t rpt_b; + uint8_t reserved1; + uint8_t noise_power; + uint8_t path_cfotail[2]; + uint8_t pcts_mask[2]; + uint8_t stream_rxevm[2]; + uint8_t path_rxsnr[2]; + uint8_t noise_power_db_lsb; + uint8_t reserved2[3]; + uint8_t stream_csi[2]; + uint8_t stream_target_csi[2]; + uint8_t sig_evm; + uint8_t reserved3; + uint8_t reserved4; +} __packed; + /* Tx MAC descriptor. */ struct r92c_tx_desc { uint32_t txdw0; @@ -950,6 +1006,8 @@ struct r92c_tx_desc { uint32_t txdw1; #define R92C_TXDW1_MACID_M 0x0000001f #define R92C_TXDW1_MACID_S 0 +#define R88E_TXDW1_MACID_M 0x0000003f +#define R88E_TXDW1_MACID_S 0 #define R92C_TXDW1_AGGEN 0x00000020 #define R92C_TXDW1_AGGBK 0x00000040 #define R92C_TXDW1_QSEL_M 0x00001f00 @@ -967,6 +1025,8 @@ struct r92c_tx_desc { #define R92C_TXDW1_PKTOFF_S 26 uint32_t txdw2; +#define R88E_TXDW2_AGGBK 0x00010000 + uint16_t txdw3; uint16_t txdseq; @@ -1096,10 +1156,16 @@ struct urtwn_softc { #define URTWN_FLAG_CCK_HIPWR 0x01 u_int chip; -#define URTWN_CHIP_92C 0x01 -#define URTWN_CHIP_92C_1T2R 0x02 -#define URTWN_CHIP_UMC 0x04 -#define URTWN_CHIP_UMC_A_CUT 0x08 +#define URTWN_CHIP_92C 0x01 +#define URTWN_CHIP_92C_1T2R 0x02 +#define URTWN_CHIP_UMC 0x04 +#define URTWN_CHIP_UMC_A_CUT 0x08 +#define URTWN_CHIP_88E 0x10 + + void (*sc_rf_write)(struct urtwn_softc *, + int, uint8_t, uint32_t); + int (*sc_power_on)(struct urtwn_softc *); + int (*sc_dma_init)(struct urtwn_softc *); uint8_t board_type; uint8_t regulatory; @@ -1118,6 +1184,11 @@ struct urtwn_softc { struct urtwn_tx_data tx_data[URTWN_TX_LIST_COUNT]; TAILQ_HEAD(, urtwn_tx_data) tx_free_list; struct r92c_rom rom; + uint8_t r88e_rom[512]; + uint8_t cck_tx_pwr[6]; + uint8_t ht40_tx_pwr[5]; + int8_t bw20_tx_pwr_diff; + int8_t ofdm_tx_pwr_diff; uint32_t rf_chnlbw[R92C_MAX_CHAINS]; #if NBPFILTER > 0 @@ -1145,7 +1216,31 @@ struct urtwn_softc { static const struct { uint16_t reg; uint8_t val; -} rtl8192cu_mac[] = { +} rtl8188eu_mac[] = { + { 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a }, + { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 }, + { 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 }, + { 0x437, 0x08 }, { 0x438, 0x00 }, { 0x439, 0x00 }, { 0x43a, 0x01 }, + { 0x43b, 0x02 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, { 0x43e, 0x06 }, + { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, { 0x442, 0x00 }, + { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, { 0x447, 0x00 }, + { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, { 0x45b, 0xb9 }, + { 0x460, 0x66 }, { 0x461, 0x66 }, { 0x480, 0x08 }, { 0x4c8, 0xff }, + { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff }, { 0x4ce, 0x01 }, + { 0x4d3, 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 }, { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, + { 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, + { 0x620, 0xff }, { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, + { 0x624, 0xff }, { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, + { 0x652, 0x20 }, { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, + { 0x63f, 0x0e }, { 0x640, 0x40 }, { 0x66e, 0x05 }, { 0x700, 0x21 }, + { 0x701, 0x43 }, { 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, + { 0x709, 0x43 }, { 0x70a, 0x65 }, { 0x70b, 0x87 } +}, rtl8192cu_mac[] = { { 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 }, { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, { 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 }, @@ -1481,6 +1576,115 @@ static const struct urtwn_bb_prog rtl8188cu_bb_prog = { }; /* + * RTL8188EU. + */ +static const uint16_t rtl8188eu_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, 0x89c, + 0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, 0xa00, 0xa04, + 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24, + 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xb2c, + 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, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, + 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, + 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74, 0xd78, 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, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00 +}; + +static const uint32_t rtl8188eu_bb_vals[] = { + 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, + 0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x569a11a9, 0x01000014, 0x66f60110, + 0x061f0649, 0x00000000, 0x27272700, 0x07000760, 0x25004000, + 0x00000808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000, + 0xccc000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00706050, + 0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002, + 0x00000201, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e7f120f, + 0x9500bb78, 0x1114d028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x00000900, 0x225b0606, 0x218075b1, 0x80000000, 0x48071d40, + 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, + 0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994, 0x0a97971c, + 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, 0x69553420, + 0x43bc0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848b, + 0x47c00bff, 0x00000036, 0x2c7f000d, 0x020610db, 0x0000001f, + 0x00b91612, 0x390000e4, 0x20f60000, 0x40000100, 0x20200000, + 0x00091521, 0x00000000, 0x00121820, 0x00007f7f, 0x00000000, + 0x000300a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932, + 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, 0x00000740, + 0x00020401, 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc43, + 0x7a8f5b6f, 0xcc979975, 0x00000000, 0x80608000, 0x00000000, + 0x00127353, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6437140a, 0x00000000, 0x00000282, 0x30032064, 0x4653de68, + 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220, + 0x000e3c24, 0x2d2d2d2d, 0x2d2d2d2d, 0x0390272d, 0x2d2d2d2d, + 0x2d2d2d2d, 0x2d2d2d2d, 0x2d2d2d2d, 0x00000000, 0x1000dc1f, + 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800, + 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102, + 0x28160d05, 0x00000008, 0x001b25a4, 0x00c00014, 0x00c00014, + 0x01000014, 0x01000014, 0x01000014, 0x01000014, 0x00c00014, + 0x01000014, 0x00c00014, 0x00c00014, 0x00c00014, 0x00c00014, + 0x00000014, 0x00000014, 0x21555448, 0x01c00014, 0x00000003, + 0x00000000, 0x00000300 +}; + +static const uint32_t rtl8188eu_agc_vals[] = { + 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, + 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, + 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001, + 0xf10f0001, 0xf0100001, 0xef110001, 0xee120001, 0xed130001, + 0xec140001, 0xeb150001, 0xea160001, 0xe9170001, 0xe8180001, + 0xe7190001, 0xe61a0001, 0xe51b0001, 0xe41c0001, 0xe31d0001, + 0xe21e0001, 0xe11f0001, 0x8a200001, 0x89210001, 0x88220001, + 0x87230001, 0x86240001, 0x85250001, 0x84260001, 0x83270001, + 0x82280001, 0x6b290001, 0x6a2a0001, 0x692b0001, 0x682c0001, + 0x672d0001, 0x662e0001, 0x652f0001, 0x64300001, 0x63310001, + 0x62320001, 0x61330001, 0x46340001, 0x45350001, 0x44360001, + 0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001, + 0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001, + 0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001, + 0xfb460001, 0xfb470001, 0xfb480001, 0xfa490001, 0xf94a0001, + 0xf84B0001, 0xf74c0001, 0xf64d0001, 0xf54e0001, 0xf44f0001, + 0xf3500001, 0xf2510001, 0xf1520001, 0xf0530001, 0xef540001, + 0xee550001, 0xed560001, 0xec570001, 0xeb580001, 0xea590001, + 0xe95a0001, 0xe85b0001, 0xe75c0001, 0xe65d0001, 0xe55e0001, + 0xe45f0001, 0xe3600001, 0xe2610001, 0xc3620001, 0xc2630001, + 0xc1640001, 0x8b650001, 0x8a660001, 0x89670001, 0x88680001, + 0x87690001, 0x866a0001, 0x856b0001, 0x846c0001, 0x676d0001, + 0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001, + 0x61730001, 0x60740001, 0x46750001, 0x45760001, 0x44770001, + 0x43780001, 0x42790001, 0x417a0001, 0x407b0001, 0x407c0001, + 0x407d0001, 0x407e0001, 0x407f0001 +}; + +static const struct urtwn_bb_prog rtl8188eu_bb_prog = { + nitems(rtl8188eu_bb_regs), + rtl8188eu_bb_regs, + rtl8188eu_bb_vals, + nitems(rtl8188eu_agc_vals), + rtl8188eu_agc_vals +}; + +/* * RTL8188RU. */ static const uint16_t rtl8188ru_bb_regs[] = { @@ -1744,6 +1948,47 @@ static const struct urtwn_rf_prog rtl8188cu_rf_prog[] = { }; /* + * RTL8188EU. + */ +static const uint8_t rtl8188eu_rf_regs[] = { + 0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57, + 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51, 0x52, 0x53, 0x56, + 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xb6, 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, 0x18, 0xfe, 0xfe, + 0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00 +}; + +static const uint32_t rtl8188eu_rf_vals[] = { + 0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060, + 0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc, + 0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001, + 0x40000, 0x00400, 0xc0000, 0x02400, 0x00009, 0x40c91, 0x99999, + 0x000a3, 0x88820, 0x76c06, 0x00000, 0x80000, 0x00180, 0x001a0, + 0x6b27d, 0x7e49d, 0x00073, 0x51ff3, 0x00086, 0x00186, + 0x00286, 0x01c25, 0x09c25, 0x11c25, 0x19c25, 0x48538, 0x00c07, + 0x4bd00, 0x739d0, 0x0adf3, 0x09df0, 0x08ded, 0x07dea, 0x06de7, + 0x054ee, 0x044eb, 0x034e8, 0x0246b, 0x01468, 0x0006d, 0x30159, + 0x68200, 0x000ce, 0x48a00, 0x65540, 0x88000, 0x020a0, 0xf02b0, + 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780, + 0x722b0, 0x6f7b0, 0x54fb0, 0x4f060, 0x30090, 0x20080, 0x10080, + 0x0f780, 0x000a0, 0x10159, 0x0f407, 0x00000, 0x00000, 0x80003, + 0x00000, 0x00000, 0x00001, 0x80000, 0x33e60 +}; + +static const struct urtwn_rf_prog rtl8188eu_rf_prog[] = { + { + nitems(rtl8188eu_rf_regs), + rtl8188eu_rf_regs, + rtl8188eu_rf_vals + } +}; + +/* * RTL8188RU. */ static const uint32_t rtl8188ru_rf_vals[] = { @@ -1782,6 +2027,10 @@ struct urtwn_txpwr { uint8_t pwr[3][28]; }; +struct urtwn_r88e_txpwr { + uint8_t pwr[6][28]; +}; + /* * Per RF chain/group/rate Tx gain values. */ @@ -1850,3 +2099,44 @@ static const struct urtwn_txpwr rtl8188ru_txagc[] = { } } } }; + +static const struct urtwn_r88e_txpwr rtl8188eu_txagc[] = { + { { /* Chain 0. */ + { /* Group 0. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 1. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 2. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 3. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 4. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 5. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + } + } } +}; |