diff options
Diffstat (limited to 'freebsd/sys/dev/rtwn/rtl8188e')
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e.h | 6 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c | 331 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c | 6 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c | 77 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h | 34 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h | 54 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c | 3 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h | 23 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c | 19 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h | 12 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c | 37 | ||||
-rw-r--r-- | freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c | 81 |
12 files changed, 552 insertions, 131 deletions
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h index 3a3c0865..ce9fa19a 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h @@ -24,9 +24,7 @@ /* * Global definitions. */ -#define R88E_PUBQ_NPAGES 142 #define R88E_TXPKTBUF_COUNT 177 -#define R88E_TX_PAGE_COUNT 169 #define R88E_MACID_MAX 63 #define R88E_RX_DMA_BUFFER_SIZE 0x2400 @@ -67,9 +65,8 @@ int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); #endif /* r88e_init.c */ -void r88e_init_bb(struct rtwn_softc *); +void r88e_init_bb_common(struct rtwn_softc *); void r88e_init_rf(struct rtwn_softc *); -int r88e_power_on(struct rtwn_softc *); /* r88e_led.c */ void r88e_set_led(struct rtwn_softc *, int, int); @@ -81,6 +78,7 @@ void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); void r88e_parse_rom(struct rtwn_softc *, uint8_t *); /* r88e_rx.c */ +int r88e_classify_intr(struct rtwn_softc *, void *, int); void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c index 592f391a..94974983 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org> + * Copyright (c) 2016-2019 Andriy Voskoboinyk <avos@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 @@ -44,16 +44,343 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwnreg.h> #include <dev/rtwn/if_rtwnvar.h> +#include <dev/rtwn/if_rtwn_debug.h> #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> +/* Registers to save and restore during IQ calibration. */ +struct r88e_iq_cal_reg_vals { + uint32_t adda[16]; + uint8_t txpause; + uint8_t bcn_ctrl[2]; + uint32_t gpio_muxcfg; + uint32_t cck0_afesetting; + 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_ant0; + uint32_t config_ant1; +}; + +static int +r88e_iq_calib_chain(struct rtwn_softc *sc, uint16_t tx[2], uint16_t rx[2]) +{ + uint32_t status; + + /* Set Rx IQ calibration mode table. */ + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); + rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf117b); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + + /* IQ calibration settings. */ + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x81004800); + + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160804); + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000); + + /* LO calibration settings. */ + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); + + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 10000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); + if (status & (1 << 28)) + return (0); /* Tx failed. */ + + /* Read Tx IQ calibration results. */ + tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0)), + R92C_POWER_IQK_RESULT); + tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0)), + R92C_POWER_IQK_RESULT); + if (tx[0] == 0x142 || tx[1] == 0x042) + return (0); /* Tx failed. */ + + rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 | (tx[0] << 16) | tx[1]); + + /* Set Rx IQ calibration mode table. */ + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); + rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ffa); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + + /* IQ calibration settings. */ + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); + + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160c05); + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160c05); + + /* LO calibration settings. */ + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); + + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 10000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); + if (status & (1 << 27)) + return (1); /* Rx failed. */ + + /* Read Rx IQ calibration results. */ + rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0)), + R92C_POWER_IQK_RESULT); + rx[1] = MS(status, R92C_POWER_IQK_RESULT); + if (rx[0] == 0x132 || rx[1] == 0x036) + return (1); /* Rx failed. */ + + return (3); /* Both Tx and Rx succeeded. */ +} + +static void +r88e_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2], + uint16_t rx[2], struct r88e_iq_cal_reg_vals *vals) +{ + /* Registers to save and restore during IQ calibration. */ + static const uint16_t reg_adda[16] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + int i; + uint32_t hssi_param1; + + if (n == 0) { + for (i = 0; i < nitems(reg_adda); i++) + vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]); + + vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE); + vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0)); + vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1)); + vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); + } + + rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); + for (i = 1; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); + + 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); + } + + if (n == 0) { + vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); + vals->ofdm0_trxpathena = + rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); + vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); + vals->fpga0_rfifacesw0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0)); + vals->fpga0_rfifacesw1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); + vals->fpga0_rfifaceoe0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); + vals->fpga0_rfifaceoe1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1)); + vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0)); + vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1)); + } + + rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000); + 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); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0); + + rtwn_write_1(sc, R92C_TXPAUSE, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + rtwn_write_1(sc, R92C_BCN_CTRL(0), + vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_BCN_CTRL(1), + vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_GPIO_MUXCFG, + vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT); + + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x0f600000); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); + + /* Run IQ calibration twice. */ + for (i = 0; i < 2; i++) { + int ret; + + ret = r88e_iq_calib_chain(sc, tx, rx); + if (ret == 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Tx failed.\n", + __func__); + tx[0] = 0xff; + tx[1] = 0xff; + rx[0] = 0xff; + rx[1] = 0xff; + } else if (ret == 1) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Rx failed.\n", + __func__); + rx[0] = 0xff; + rx[1] = 0xff; + } else if (ret == 3) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Both Tx and Rx" + " succeeded.\n", __func__); + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: results for run %d: tx[0] 0x%x, tx[1] 0x%x, rx[0] 0x%x, " + "rx[1] 0x%x\n", __func__, n, tx[0], tx[1], rx[0], rx[1]); + + rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting); + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1); + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0); + rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 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); + } + + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], vals->adda[i]); + + rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause); + rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]); + rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]); + rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg); + } +} + +#define RTWN_IQ_CAL_MAX_TOLERANCE 5 +static int +r88e_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2], + uint16_t rx1[2], uint16_t tx2[2], uint16_t rx2[2]) +{ + int i, tx_ok, rx_ok; + + tx_ok = rx_ok = 0; + for (i = 0; i < 2; i++) { + if (tx1[i] == 0xff || tx2[i] == 0xff || + rx1[i] == 0xff || rx2[i] == 0xff) + continue; + + tx_ok = (abs(tx1[i] - tx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); + rx_ok = (abs(rx1[i] - rx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); + } + + return (tx_ok && rx_ok); +} +#undef RTWN_IQ_CAL_MAX_TOLERANCE + +static void +r88e_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], + uint16_t rx[2]) +{ + uint32_t reg, val, x; + long y, tx_c; + + if (tx[0] == 0xff || tx[1] == 0xff) + return; + + reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0)); + val = ((reg >> 22) & 0x3ff); + x = tx[0]; + if (x & 0x00000200) + x |= 0xfffffc00; + reg = (((x * val) >> 8) & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x3ff, reg); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, + ((x * val) & 0x80) << 24); + + y = tx[1]; + if (y & 0x00000200) + y |= 0xfffffc00; + tx_c = (y * val) >> 8; + rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000, + (tx_c & 0x3c0) << 22); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x003f0000, + (tx_c & 0x3f) << 16); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000, + ((y * val) & 0x80) << 22); + + if (rx[0] == 0xff || rx[1] == 0xff) + return; + + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff, + rx[0] & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00, + (rx[1] & 0x3f) << 10); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, + (rx[1] & 0x3c0) << 22); +} + +#define RTWN_IQ_CAL_NRUN 3 void r88e_iq_calib(struct rtwn_softc *sc) { - /* XXX TODO */ + struct r88e_iq_cal_reg_vals vals; + uint16_t tx[RTWN_IQ_CAL_NRUN][2], rx[RTWN_IQ_CAL_NRUN][2]; + int n, valid; + + KASSERT(sc->ntxchains == 1, + ("%s: only 1T1R configuration is supported!\n", __func__)); + + valid = 0; + for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { + r88e_iq_calib_run(sc, n, tx[n], rx[n], &vals); + + if (n == 0) + continue; + + /* Valid results remain stable after consecutive runs. */ + valid = r88e_iq_calib_compare_results(sc, tx[n - 1], + rx[n - 1], tx[n], rx[n]); + if (valid) + break; + } + + if (valid) + r88e_iq_calib_write_results(sc, tx[n], rx[n]); } +#undef RTWN_IQ_CAL_NRUN void r88e_temp_measure(struct rtwn_softc *sc) diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c index ddc9d0a4..ff48d244 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c @@ -111,7 +111,11 @@ r88e_fw_reset(struct rtwn_softc *sc, int reason) reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); - rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); + + if (reason != RTWN_FW_RESET_SHUTDOWN) { + rtwn_write_2(sc, R92C_SYS_FUNC_EN, + reg | R92C_SYS_FUNC_EN_CPUEN); + } } void diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c index 5225c43f..8c5bbac2 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c @@ -72,20 +72,8 @@ r88e_crystalcap_write(struct rtwn_softc *sc) } void -r88e_init_bb(struct rtwn_softc *sc) +r88e_init_bb_common(struct rtwn_softc *sc) { - - /* Enable BB and RF. */ - rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_DIO_RF); - - rtwn_write_1(sc, R92C_RF_CTRL, - R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); - rtwn_write_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | - R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); - r92c_init_bb_common(sc); rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); @@ -95,66 +83,3 @@ r88e_init_bb(struct rtwn_softc *sc) r88e_crystalcap_write(sc); } - -int -r88e_power_on(struct rtwn_softc *sc) -{ -#define RTWN_CHK(res) do { \ - if (res != 0) \ - return (EIO); \ -} while(0) - int ntries; - - /* Wait for power ready bit. */ - for (ntries = 0; ntries < 5000; ntries++) { - if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) - break; - rtwn_delay(sc, 10); - } - if (ntries == 5000) { - device_printf(sc->sc_dev, - "timeout waiting for chip power up\n"); - return (ETIMEDOUT); - } - - /* Reset BB. */ - RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); - - RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); - - /* Disable HWPDN. */ - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_APDM_HPDN, 0, 1)); - - /* Disable WL suspend. */ - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); - - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); - for (ntries = 0; ntries < 5000; ntries++) { - if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & - R92C_APS_FSMCO_APFM_ONMAC)) - break; - rtwn_delay(sc, 10); - } - if (ntries == 5000) - return (ETIMEDOUT); - - /* Enable LDO normal mode. */ - RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, - R92C_LPLDO_CTRL_SLEEP, 0)); - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ - RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); - RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, - R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | - R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | - R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | - ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | - R92C_CR_CALTMR_EN)); - - return (0); -#undef RTWN_CHK -} diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h index 28f4b1fb..8ec5502d 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h @@ -37,7 +37,7 @@ struct rtwn_r88e_txpwr { /* * MAC initialization values. */ -static const struct rtwn_mac_prog rtl8188eu_mac[] = { +static const struct rtwn_mac_prog rtl8188e_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 }, @@ -66,7 +66,7 @@ static const struct rtwn_mac_prog rtl8188eu_mac[] = { /* * Baseband initialization values. */ -static const uint16_t rtl8188eu_bb_regs[] = { +static const uint16_t rtl8188e_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, @@ -93,7 +93,7 @@ static const uint16_t rtl8188eu_bb_regs[] = { 0xed8, 0xedc, 0xee0, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00 }; -static const uint32_t rtl8188eu_bb_vals[] = { +static const uint32_t rtl8188e_bb_vals[] = { 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, 0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -135,17 +135,17 @@ static const uint32_t rtl8188eu_bb_vals[] = { 0x00000000, 0x00000300 }; -static const struct rtwn_bb_prog rtl8188eu_bb[] = { +static const struct rtwn_bb_prog rtl8188e_bb[] = { { - nitems(rtl8188eu_bb_regs), - rtl8188eu_bb_regs, - rtl8188eu_bb_vals, + nitems(rtl8188e_bb_regs), + rtl8188e_bb_regs, + rtl8188e_bb_vals, { 0 }, NULL } }; -static const uint32_t rtl8188eu_agc_vals[] = { +static const uint32_t rtl8188e_agc_vals[] = { 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001, @@ -174,10 +174,10 @@ static const uint32_t rtl8188eu_agc_vals[] = { 0x407d0001, 0x407e0001, 0x407f0001 }; -static const struct rtwn_agc_prog rtl8188eu_agc[] = { +static const struct rtwn_agc_prog rtl8188e_agc[] = { { - nitems(rtl8188eu_agc_vals), - rtl8188eu_agc_vals, + nitems(rtl8188e_agc_vals), + rtl8188e_agc_vals, { 0 }, NULL } @@ -186,7 +186,7 @@ static const struct rtwn_agc_prog rtl8188eu_agc[] = { /* * RF initialization values. */ -static const uint8_t rtl8188eu_rf_regs[] = { +static const uint8_t rtl8188e_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, @@ -199,7 +199,7 @@ static const uint8_t rtl8188eu_rf_regs[] = { 0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00 }; -static const uint32_t rtl8188eu_rf_vals[] = { +static const uint32_t rtl8188e_rf_vals[] = { 0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc, 0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001, @@ -216,11 +216,11 @@ static const uint32_t rtl8188eu_rf_vals[] = { 0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60 }; -static const struct rtwn_rf_prog rtl8188eu_rf[] = { +static const struct rtwn_rf_prog rtl8188e_rf[] = { { - nitems(rtl8188eu_rf_regs), - rtl8188eu_rf_regs, - rtl8188eu_rf_vals, + nitems(rtl8188e_rf_regs), + rtl8188e_rf_regs, + rtl8188e_rf_vals, { 0 }, NULL }, diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h index f6f26fa4..94b9a660 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h @@ -32,6 +32,7 @@ #define R88E_HISR 0x0b4 #define R88E_HIMRE 0x0b8 #define R88E_HISRE 0x0bc +#define R88E_XCK_OUT_CTRL 0x07c /* MAC General Configuration. */ #define R88E_32K_CTRL 0x194 #define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4) @@ -45,16 +46,49 @@ /* Bits for R88E_HIMR. */ -#define R88E_HIMR_CPWM 0x00000100 -#define R88E_HIMR_CPWM2 0x00000200 -#define R88E_HIMR_TBDER 0x04000000 -#define R88E_HIMR_PSTIMEOUT 0x20000000 +#define R88E_HIMR_ROK 0x00000001 /* receive DMA OK */ +#define R88E_HIMR_RDU 0x00000002 /* Rx descriptor unavailable */ +#define R88E_HIMR_VODOK 0x00000004 /* AC_VO DMA OK */ +#define R88E_HIMR_VIDOK 0x00000008 /* AC_VI DMA OK */ +#define R88E_HIMR_BEDOK 0x00000010 /* AC_BE DMA OK */ +#define R88E_HIMR_BKDOK 0x00000020 /* AC_BK DMA OK */ +#define R88E_HIMR_MGNTDOK 0x00000040 /* management queue DMA OK */ +#define R88E_HIMR_HIGHDOK 0x00000080 /* high queue DMA OK */ +#define R88E_HIMR_CPWM 0x00000100 /* CPU power mode intr 1 */ +#define R88E_HIMR_CPWM2 0x00000200 /* CPU power mode intr 2 */ +#define R88E_HIMR_C2HCMD 0x00000400 /* C2H command interrupt */ +#define R88E_HIMR_HISR 0x00000800 /* (HISR & HIMR) != 0 */ +#define R88E_HIMR_ATIMEND 0x00001000 /* ATIM window end interrupt */ +#define R88E_HIMR_HSISR 0x00008000 /* (HSIMR & HSISR) != 0 */ +#define R88E_HIMR_BCNDERR 0x00010000 /* beacon queue DMA error */ +#define R88E_HIMR_BCNINT 0x00100000 /* beacon DMA interrupt 0 */ +#define R88E_HIMR_TSF32 0x01000000 /* TSF 32 bit interrupt */ +#define R88E_HIMR_TBDOK 0x02000000 /* beacon transmit OK */ +#define R88E_HIMR_TBDER 0x04000000 /* beacon transmit error */ +#define R88E_HIMR_GTIMER3 0x08000000 /* GTIMER3 interrupt */ +#define R88E_HIMR_GTIMER4 0x10000000 /* GTIMER4 interrupt */ +#define R88E_HIMR_PSTIMEOUT 0x20000000 /* powersave timeout */ +#define R88E_HIMR_TXRPT 0x40000000 /* Tx report interrupt */ /* Bits for R88E_HIMRE.*/ -#define R88E_HIMRE_RXFOVW 0x00000100 -#define R88E_HIMRE_TXFOVW 0x00000200 -#define R88E_HIMRE_RXERR 0x00000400 -#define R88E_HIMRE_TXERR 0x00000800 +#define R88E_HIMRE_RXFOVW 0x00000100 /* receive FIFO overflow */ +#define R88E_HIMRE_TXFOVW 0x00000200 /* transmit FIFO overflow */ +#define R88E_HIMRE_RXERR 0x00000400 /* receive error */ +#define R88E_HIMRE_TXERR 0x00000800 /* transmit error */ +#define R88E_HIMRE_BCNDOK1 0x00004000 /* beacon queue DMA OK (1) */ +#define R88E_HIMRE_BCNDOK2 0x00008000 /* beacon queue DMA OK (2) */ +#define R88E_HIMRE_BCNDOK3 0x00010000 /* beacon queue DMA OK (3) */ +#define R88E_HIMRE_BCNDOK4 0x00020000 /* beacon queue DMA OK (4) */ +#define R88E_HIMRE_BCNDOK5 0x00040000 /* beacon queue DMA OK (5) */ +#define R88E_HIMRE_BCNDOK6 0x00080000 /* beacon queue DMA OK (6) */ +#define R88E_HIMRE_BCNDOK7 0x00100000 /* beacon queue DMA OK (7) */ +#define R88E_HIMRE_BCNDMAINT1 0x00200000 /* beacon DMA interrupt 1 */ +#define R88E_HIMRE_BCNDMAINT2 0x00400000 /* beacon DMA interrupt 2 */ +#define R88E_HIMRE_BCNDMAINT3 0x00800000 /* beacon DMA interrupt 3 */ +#define R88E_HIMRE_BCNDMAINT4 0x01000000 /* beacon DMA interrupt 4 */ +#define R88E_HIMRE_BCNDMAINT5 0x02000000 /* beacon DMA interrupt 5 */ +#define R88E_HIMRE_BCNDMAINT6 0x04000000 /* beacon DMA interrupt 6 */ +#define R88E_HIMRE_BCNDMAINT7 0x08000000 /* beacon DMA interrupt 7 */ /* Bits for R88E_TX_RPT_CTRL. */ #define R88E_TX_RPT1_ENA 0x01 @@ -79,6 +113,7 @@ * RF (6052) registers. */ #define R88E_RF_T_METER 0x42 +#define R88E_RF_WE_LUT 0xef /* Bits for R92C_RF_CHNLBW. */ #define R88E_RF_CHNLBW_BW20 0x00c00 @@ -88,4 +123,7 @@ #define R88E_RF_T_METER_VAL_S 10 #define R88E_RF_T_METER_START 0x30000 +/* Bits for R88E_XCK_OUT_CTRL. */ +#define R88E_XCK_OUT_CTRL_EN 1 + #endif /* R88E_REG_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c index e1337dba..3afa2910 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c @@ -83,5 +83,6 @@ r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf) __func__,rs->regulatory); sc->thermal_meter = rom->thermal_meter; - IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); + + rtwn_r92c_set_rom_opts(sc, buf); } diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h index c80028e0..d5d97ffb 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h @@ -44,11 +44,24 @@ struct r88e_rom { uint8_t reserved4[3]; uint8_t rf_ant_opt; uint8_t reserved5[6]; - uint16_t vid; - uint16_t pid; - uint8_t usb_opt; - uint8_t reserved6[2]; - uint8_t macaddr[IEEE80211_ADDR_LEN]; + + union { + struct { + uint16_t vid; + uint16_t pid; + uint8_t usb_opt; + uint8_t reserved6[2]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + } __packed usb; + + struct { + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint16_t vid; + uint16_t pid; + uint8_t reserved6[3]; + } __packed pci; + } __packed diff_d0; + uint8_t reserved7[2]; uint8_t string[33]; /* "realtek 802.11n NIC" */ uint8_t reserved8[256]; diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c index 53cc722f..eee2f63f 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -58,6 +58,25 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e_rx_desc.h> +int +r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + struct r92c_rx_stat *stat = buf; + int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT); + + switch (report_sel) { + case R88E_RXDW3_RPT_RX: + return (RTWN_RX_DATA); + case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */ + case R88E_RXDW3_RPT_TX2: /* periodical Tx report */ + return (RTWN_RX_TX_REPORT); + case R88E_RXDW3_RPT_HIS: + return (RTWN_RX_OTHER); + default: /* shut up the compiler */ + return (RTWN_RX_DATA); + } +} + void r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h index 85b637cb..e79b1387 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h @@ -25,15 +25,21 @@ /* + * Global definitions. + */ +#define R88EU_PUBQ_NPAGES 142 +#define R88EU_TX_PAGE_COUNT 169 + + +/* * Function declarations. */ /* r88eu_init.c */ +void r88eu_init_bb(struct rtwn_softc *); +int r88eu_power_on(struct rtwn_softc *); void r88eu_power_off(struct rtwn_softc *); void r88eu_init_intr(struct rtwn_softc *); void r88eu_init_rx_agg(struct rtwn_softc *); void r88eu_post_init(struct rtwn_softc *); -/* r88eu_rx.c */ -int r88eu_classify_intr(struct rtwn_softc *, void *, int); - #endif /* RTL8188EU_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index 73cc7856..6b153bcd 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h> #include <dev/rtwn/rtl8188e/r88e_priv.h> +#include <dev/rtwn/rtl8188e/r88e_rom_image.h> /* for 'macaddr' field */ #include <dev/rtwn/rtl8188e/usb/r88eu.h> @@ -68,6 +69,14 @@ static struct rtwn_r88e_txpwr r88e_txpwr; void r88eu_attach(struct rtwn_usb_softc *); static void +r88eu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r88e_rom *rom = (struct r88e_rom *)buf; + + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->diff_d0.usb.macaddr); +} + +static void r88e_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; @@ -95,7 +104,7 @@ r88eu_attach_private(struct rtwn_softc *sc) rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq; rs->rs_tx_setup_macid = r88e_tx_setup_macid; - rs->rs_set_name = rtwn_nop_softc; /* not used */ + rs->rs_set_rom_opts = r88eu_set_macaddr; rs->rf_read_delay[0] = 10; rs->rf_read_delay[1] = 100; @@ -132,7 +141,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_get_rx_stats = r88e_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; - sc->sc_classify_intr = r88eu_classify_intr; + sc->sc_classify_intr = r88e_classify_intr; sc->sc_handle_tx_report = r88e_ratectl_tx_complete; sc->sc_handle_c2h_report = r88e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; @@ -142,7 +151,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_efuse_postread = rtwn_nop_softc; sc->sc_parse_rom = r88e_parse_rom; sc->sc_set_led = r88e_set_led; - sc->sc_power_on = r88e_power_on; + sc->sc_power_on = r88eu_power_on; sc->sc_power_off = r88eu_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r88e_fw_reset; @@ -151,7 +160,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; - sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ + sc->sc_iq_calib = r88e_iq_calib; sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r88eu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; @@ -174,29 +183,29 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_init_ampdu = rtwn_nop_softc; sc->sc_init_intr = r88eu_init_intr; sc->sc_init_edca = r92c_init_edca; - sc->sc_init_bb = r88e_init_bb; + sc->sc_init_bb = r88eu_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r88eu_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->mac_prog = &rtl8188eu_mac[0]; - sc->mac_size = nitems(rtl8188eu_mac); - sc->bb_prog = &rtl8188eu_bb[0]; - sc->bb_size = nitems(rtl8188eu_bb); - sc->agc_prog = &rtl8188eu_agc[0]; - sc->agc_size = nitems(rtl8188eu_agc); - sc->rf_prog = &rtl8188eu_rf[0]; + sc->mac_prog = &rtl8188e_mac[0]; + sc->mac_size = nitems(rtl8188e_mac); + sc->bb_prog = &rtl8188e_bb[0]; + sc->bb_size = nitems(rtl8188e_bb); + sc->agc_prog = &rtl8188e_agc[0]; + sc->agc_size = nitems(rtl8188e_agc); + sc->rf_prog = &rtl8188e_rf[0]; sc->name = "RTL8188EU"; sc->fwname = "rtwn-rtl8188eufw"; sc->fwsig = 0x88e; - sc->page_count = R88E_TX_PAGE_COUNT; + sc->page_count = R88EU_TX_PAGE_COUNT; sc->pktbuf_count = R88E_TXPKTBUF_COUNT; sc->ackto = 0x40; - sc->npubqpages = R88E_PUBQ_NPAGES; + sc->npubqpages = R88EU_PUBQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92cu_tx_desc); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c index 2c776671..bfe3681e 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c @@ -57,6 +57,87 @@ __FBSDID("$FreeBSD$"); void +r88eu_init_bb(struct rtwn_softc *sc) +{ + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | + R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); + + r88e_init_bb_common(sc); +} + +int +r88eu_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Reset BB. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); + + RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); + + /* Disable HWPDN. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Disable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable LDO normal mode. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, + R92C_LPLDO_CTRL_SLEEP, 0)); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + return (0); +#undef RTWN_CHK +} + +void r88eu_power_off(struct rtwn_softc *sc) { uint8_t reg; |