diff options
author | Kevin Lo <kevlo@cvs.openbsd.org> | 2018-10-02 02:05:35 +0000 |
---|---|---|
committer | Kevin Lo <kevlo@cvs.openbsd.org> | 2018-10-02 02:05:35 +0000 |
commit | 7db65d7b0d2bc1bfc9a7de5b967193762dfb4d97 (patch) | |
tree | 9be45cdbc2893a5ecc92417d2bc9f86f759fe938 /sys/dev/ic | |
parent | ba7b94a14adb3c513a0aab9ead2fb3d41f43e3e2 (diff) |
Add support for RT3290 chipset by James Hastings.
Tested by me and James Hastings.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/rt2860.c | 187 | ||||
-rw-r--r-- | sys/dev/ic/rt2860reg.h | 115 |
2 files changed, 281 insertions, 21 deletions
diff --git a/sys/dev/ic/rt2860.c b/sys/dev/ic/rt2860.c index 3a34c866913..c6c811c835e 100644 --- a/sys/dev/ic/rt2860.c +++ b/sys/dev/ic/rt2860.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860.c,v 1.95 2017/10/26 15:00:28 mpi Exp $ */ +/* $OpenBSD: rt2860.c,v 1.96 2018/10/02 02:05:34 kevlo Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> @@ -17,7 +17,8 @@ */ /*- - * Ralink Technology RT2860/RT3090/RT3390/RT3562/RT5390/RT5392 chipset driver + * Ralink Technology RT2860/RT3090/RT3290/RT3390/RT3562/RT5390/ + * RT5392 chipset driver * http://www.ralinktech.com/ */ @@ -97,6 +98,7 @@ void rt2860_ampdu_rx_stop(struct ieee80211com *, int rt2860_newstate(struct ieee80211com *, enum ieee80211_state, int); uint16_t rt3090_efuse_read_2(struct rt2860_softc *, uint16_t); +uint16_t rt3290_efuse_read_2(struct rt2860_softc *, uint16_t); uint16_t rt2860_eeprom_read_2(struct rt2860_softc *, uint16_t); void rt2860_intr_coherent(struct rt2860_softc *); void rt2860_drain_stats_fifo(struct rt2860_softc *); @@ -147,6 +149,7 @@ const char * rt2860_get_rf(uint16_t); int rt2860_read_eeprom(struct rt2860_softc *); int rt2860_bbp_init(struct rt2860_softc *); void rt5390_bbp_init(struct rt2860_softc *); +int rt3290_wlan_enable(struct rt2860_softc *); int rt2860_txrx_enable(struct rt2860_softc *); int rt2860_init(struct ifnet *); void rt2860_stop(struct ifnet *, int); @@ -172,6 +175,8 @@ static const struct { uint8_t val; } rt2860_def_bbp[] = { RT2860_DEF_BBP +},rt3290_def_bbp[] = { + RT3290_DEF_BBP },rt5390_def_bbp[] = { RT5390_DEF_BBP }; @@ -194,6 +199,8 @@ static const struct { uint8_t val; } rt3090_def_rf[] = { RT3070_DEF_RF +}, rt3290_def_rf[] = { + RT3290_DEF_RF }, rt3572_def_rf[] = { RT3572_DEF_RF }, rt5390_def_rf[] = { @@ -208,14 +215,19 @@ rt2860_attach(void *xsc, int id) struct rt2860_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; int qid, ntries, error; - uint32_t tmp; + uint32_t tmp, reg; sc->amrr.amrr_min_success_threshold = 1; sc->amrr.amrr_max_success_threshold = 15; + if (id == PCI_PRODUCT_RALINK_RT3290) + reg = RT2860_PCI_CFG; + else + reg = RT2860_ASIC_VER_ID; + /* wait for NIC to initialize */ for (ntries = 0; ntries < 100; ntries++) { - tmp = RAL_READ(sc, RT2860_ASIC_VER_ID); + tmp = RAL_READ(sc, reg); if (tmp != 0 && tmp != 0xffffffff) break; DELAY(10); @@ -286,7 +298,11 @@ rt2860_attachhook(struct device *self) struct ifnet *ifp = &ic->ic_if; int i, error; - error = loadfirmware("ral-rt2860", &sc->ucode, &sc->ucsize); + if (sc->mac_ver == 0x3290) { + error = loadfirmware("ral-rt3290", &sc->ucode, &sc->ucsize); + } else { + error = loadfirmware("ral-rt2860", &sc->ucode, &sc->ucsize); + } if (error != 0) { printf("%s: error %d, could not read firmware file %s\n", sc->sc_dev.dv_xname, error, "ral-rt2860"); @@ -1026,6 +1042,45 @@ rt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) return (addr & 2) ? tmp >> 16 : tmp & 0xffff; } +/* Read 16 bits from eFUSE ROM (RT3290 only) */ +uint16_t +rt3290_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) +{ + uint32_t tmp; + uint16_t reg; + int ntries; + + addr *= 2; + /*- + * Read one 16-byte block into registers EFUSE_DATA[0-3]: + * DATA3: 3 2 1 0 + * DATA2: 7 6 5 4 + * DATA1: B A 9 8 + * DATA0: F E D C + */ + tmp = RAL_READ(sc, RT3290_EFUSE_CTRL); + tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); + tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; + RAL_WRITE(sc, RT3290_EFUSE_CTRL, tmp); + for (ntries = 0; ntries < 500; ntries++) { + tmp = RAL_READ(sc, RT3290_EFUSE_CTRL); + if (!(tmp & RT3070_EFSROM_KICK)) + break; + DELAY(2); + } + if (ntries == 500) + return 0xffff; + + if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) + return 0xffff; /* address not found */ + + /* determine to which 32-bit register our 16-bit word belongs */ + reg = RT3290_EFUSE_DATA3 + (addr & 0xc); + tmp = RAL_READ(sc, reg); + + return (addr & 2) ? tmp >> 16 : tmp & 0xffff; +} + /* * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, * 93C66 or 93C86). @@ -2374,6 +2429,19 @@ rt5390_set_chan(struct rt2860_softc *sc, u_int chan) else rf = 0x06; rt3090_rf_write(sc, 59, rf); + } else if (sc->mac_ver == 0x3290) { + if (chan == 6) + rt2860_mcu_bbp_write(sc, 68, 0x0c); + else + rt2860_mcu_bbp_write(sc, 68, 0x0b); + + if (chan >= 1 && chan < 6) + rf = 0x0f; + else if (chan >= 7 && chan <= 11) + rf = 0x0e; + else if (chan >= 12 && chan <= 14) + rf = 0x0d; + rt3090_rf_write(sc, 59, rf); } /* Tx/Rx h20M */ @@ -2525,7 +2593,12 @@ rt5390_rf_init(struct rt2860_softc *sc) for (i = 0; i < nitems(rt5392_def_rf); i++) { rt3090_rf_write(sc, rt5392_def_rf[i].reg, rt5392_def_rf[i].val); - } + } + } else if (sc->mac_ver == 0x3290) { + for (i = 0; i < nitems(rt3290_def_rf); i++) { + rt3090_rf_write(sc, rt3290_def_rf[i].reg, + rt3290_def_rf[i].val); + } } else { for (i = 0; i < nitems(rt5390_def_rf); i++) { rt3090_rf_write(sc, rt5390_def_rf[i].reg, @@ -2545,7 +2618,8 @@ rt5390_rf_init(struct rt2860_softc *sc) RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); - if (sc->mac_ver == 0x5390) + if (sc->mac_ver == 0x3290 || + sc->mac_ver == 0x5390) rt3090_set_rx_antenna(sc, 0); /* Patch RSSI inaccurate issue. */ @@ -2554,7 +2628,8 @@ rt5390_rf_init(struct rt2860_softc *sc) rt2860_mcu_bbp_write(sc, 81, 0x33); /* Enable DC filter. */ - if (sc->mac_rev >= 0x0211) + if (sc->mac_rev >= 0x0211 || + sc->mac_ver == 0x3290) rt2860_mcu_bbp_write(sc, 103, 0xc0); bbp = rt2860_mcu_bbp_read(sc, 138); @@ -3095,6 +3170,7 @@ rt2860_get_rf(uint16_t rev) case RT3070_RF_3052: return "RT3052"; case RT3070_RF_3320: return "RT3320"; case RT3070_RF_3053: return "RT3053"; + case RT3290_RF_3290: return "RT3290"; case RT5390_RF_5360: return "RT5360"; case RT5390_RF_5390: return "RT5390"; case RT5390_RF_5392: return "RT5392"; @@ -3113,7 +3189,12 @@ rt2860_read_eeprom(struct rt2860_softc *sc) /* check whether the ROM is eFUSE ROM or EEPROM */ sc->sc_srom_read = rt2860_eeprom_read_2; - if (sc->mac_ver >= 0x3071) { + if (sc->mac_ver == 0x3290) { + tmp = RAL_READ(sc, RT3290_EFUSE_CTRL); + DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp)); + if (tmp & RT3070_SEL_EFUSE) + sc->sc_srom_read = rt3290_efuse_read_2; + } else if (sc->mac_ver >= 0x3071) { tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp)); if (tmp & RT3070_SEL_EFUSE) @@ -3179,7 +3260,8 @@ rt2860_read_eeprom(struct rt2860_softc *sc) /* read RF information */ val = rt2860_srom_read(sc, RT2860_EEPROM_ANTENNA); - if (sc->mac_ver >= 0x5390) + DPRINTF(("EEPROM ANT 0x%04x\n", val)); + if (sc->mac_ver >= 0x5390 || sc->mac_ver == 0x3290) sc->rf_rev = rt2860_srom_read(sc, RT2860_EEPROM_CHIPID); else sc->rf_rev = (val >> 8) & 0xf; @@ -3423,7 +3505,8 @@ rt2860_bbp_init(struct rt2860_softc *sc) } /* initialize BBP registers to default values */ - if (sc->mac_ver >= 0x5390) + if (sc->mac_ver >= 0x5390 || + sc->mac_ver == 0x3290) rt5390_bbp_init(sc); else { for (i = 0; i < nitems(rt2860_def_bbp); i++) { @@ -3463,10 +3546,16 @@ rt5390_bbp_init(struct rt2860_softc *sc) /* Avoid data lost and CRC error. */ bbp = rt2860_mcu_bbp_read(sc, 4); rt2860_mcu_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); - - for (i = 0; i < nitems(rt5390_def_bbp); i++) { - rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg, - rt5390_def_bbp[i].val); + if (sc->mac_ver == 0x3290) { + for (i = 0; i < nitems(rt3290_def_bbp); i++) { + rt2860_mcu_bbp_write(sc, rt3290_def_bbp[i].reg, + rt3290_def_bbp[i].val); + } + } else { + for (i = 0; i < nitems(rt5390_def_bbp); i++) { + rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg, + rt5390_def_bbp[i].val); + } } if (sc->mac_ver == 0x5392) { @@ -3487,6 +3576,44 @@ rt5390_bbp_init(struct rt2860_softc *sc) } int +rt3290_wlan_enable(struct rt2860_softc *sc) +{ + uint32_t tmp; + int ntries; + + /* enable chip and check readiness */ + tmp = RAL_READ(sc, RT3290_WLAN_CTRL); + tmp |= RT3290_WLAN_EN | RT3290_FRC_WL_ANT_SET | + RT3290_GPIO_OUT_OE_ALL; + RAL_WRITE(sc, RT3290_WLAN_CTRL, tmp); + + for (ntries = 0; ntries < 200; ntries++) { + tmp = RAL_READ(sc, RT3290_CMB_CTRL); + if ((tmp & RT3290_PLL_LD) && + (tmp & RT3290_XTAL_RDY)) + break; + DELAY(20); + } + if (ntries == 200) + return EIO; + + /* toggle reset */ + tmp = RAL_READ(sc, RT3290_WLAN_CTRL); + tmp |= RT3290_WLAN_RESET | RT3290_WLAN_CLK_EN; + tmp &= ~RT3290_PCIE_APP0_CLK_REQ; + RAL_WRITE(sc, RT3290_WLAN_CTRL, tmp); + DELAY(20); + tmp &= ~RT3290_WLAN_RESET; + RAL_WRITE(sc, RT3290_WLAN_CTRL, tmp); + DELAY(1000); + + /* clear garbage interrupts */ + RAL_WRITE(sc, RT2860_INT_STATUS, 0x7fffffff); + + return 0; +} + +int rt2860_txrx_enable(struct rt2860_softc *sc) { uint32_t tmp; @@ -3550,7 +3677,22 @@ rt2860_init(struct ifnet *ifp) sc->sc_flags |= RT2860_ENABLED; } - if (sc->rfswitch) { + if (sc->mac_ver == 0x3290) { + if ((error = rt3290_wlan_enable(sc)) != 0) { + printf("%s: could not enable wlan\n", + sc->sc_dev.dv_xname); + rt2860_stop(ifp, 1); + return error; + } + } + + if (sc->mac_ver == 0x3290 && sc->rfswitch){ + /* hardware has a radio switch on GPIO pin 0 */ + if (!(RAL_READ(sc, RT3290_WLAN_CTRL) & RT3290_RADIO_EN)) { + printf("%s: radio is disabled by hardware switch\n", + sc->sc_dev.dv_xname); + } + } else if (sc->rfswitch) { /* hardware has a radio switch on GPIO pin 2 */ if (!(RAL_READ(sc, RT2860_GPIO_CTRL) & (1 << 2))) { printf("%s: radio is disabled by hardware switch\n", @@ -3621,7 +3763,8 @@ rt2860_init(struct ifnet *ifp) for (i = 0; i < nitems(rt2860_def_mac); i++) RAL_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); - if (sc->mac_ver >= 0x5390) + if (sc->mac_ver == 0x3290 || + sc->mac_ver >= 0x5390) RAL_WRITE(sc, RT2860_TX_SW_CFG0, 0x00000404); else if (sc->mac_ver >= 0x3071) { /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ @@ -3719,6 +3862,7 @@ rt2860_init(struct ifnet *ifp) /* select Main antenna for 1T1R devices */ if (sc->rf_rev == RT3070_RF_2020 || sc->rf_rev == RT3070_RF_3020 || + sc->rf_rev == RT3290_RF_3290 || sc->rf_rev == RT3070_RF_3320 || sc->rf_rev == RT5390_RF_5390) rt3090_set_rx_antenna(sc, 0); @@ -3728,7 +3872,8 @@ rt2860_init(struct ifnet *ifp) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1], 0); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2], 0); - if (sc->mac_ver >= 0x5390) + if (sc->mac_ver == 0x3290 || + sc->mac_ver >= 0x5390) rt5390_rf_init(sc); else if (sc->mac_ver >= 0x3071) rt3090_rf_init(sc); @@ -3736,7 +3881,8 @@ rt2860_init(struct ifnet *ifp) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_SLEEP, 0x02ff, 1); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_WAKEUP, 0, 1); - if (sc->mac_ver >= 0x5390) + if (sc->mac_ver == 0x3290 || + sc->mac_ver >= 0x5390) rt5390_rf_wakeup(sc); else if (sc->mac_ver >= 0x3071) rt3090_rf_wakeup(sc); @@ -3982,7 +4128,8 @@ rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; - if (sc->mac_ver >= 0x5390) + if (sc->mac_ver == 0x3290 || + sc->mac_ver >= 0x5390) rt5390_set_chan(sc, chan); else if (sc->mac_ver >= 0x3071) rt3090_set_chan(sc, chan); diff --git a/sys/dev/ic/rt2860reg.h b/sys/dev/ic/rt2860reg.h index bcd15f783de..c3bddf6f098 100644 --- a/sys/dev/ic/rt2860reg.h +++ b/sys/dev/ic/rt2860reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860reg.h,v 1.34 2017/05/31 03:45:15 jsg Exp $ */ +/* $OpenBSD: rt2860reg.h,v 1.35 2018/10/02 02:05:34 kevlo Exp $ */ /*- * Copyright (c) 2007 @@ -24,6 +24,18 @@ #define RT2860_PCI_SYSCTRL 0x000c #define RT2860_PCIE_JTAG 0x0010 +/* RT3290 registers */ +#define RT3290_CMB_CTRL 0x0020 +#define RT3290_EFUSE_CTRL 0x0024 +#define RT3290_EFUSE_DATA3 0x0028 +#define RT3290_EFUSE_DATA2 0x002c +#define RT3290_EFUSE_DATA1 0x0030 +#define RT3290_EFUSE_DATA0 0x0034 +#define RT3290_OSC_CTRL 0x0038 +#define RT3290_COEX_CFG0 0x0040 +#define RT3290_PLL_CTRL 0x0050 +#define RT3290_WLAN_CTRL 0x0080 + #define RT3090_AUX_CTRL 0x010c #define RT3070_OPT_14 0x0114 @@ -224,6 +236,41 @@ #define RT2860_Q (1 << 3) #define RT2860_SHIFT_Q 3 +/* possible flags for register RT3290_CMB_CTRL */ +#define RT3290_XTAL_RDY (1U << 22) +#define RT3290_PLL_LD (1U << 23) +#define RT3290_LDO_CORE_LEVEL (0xf << 24) +#define RT3290_LDO_BGSEL (3 << 29) +#define RT3290_LDO3_EN (1U << 30) +#define RT3290_LDO0_EN (1U << 31) + +/* possible flags for register RT3290_OSC_CTRL */ +#define RT3290_OSC_REF_CYCLE 0x1fff +#define RT3290_OSC_CAL_CNT (0xfff << 16) +#define RT3290_OSC_CAL_ACK (1U << 28) +#define RT3290_OSC_CLK_32K_VLD (1U << 29) +#define RT3290_OSC_CAL_REQ (1U << 30) +#define RT3290_ROSC_EN (1U << 31) + +/* possible flags for register RT3290_COEX_CFG0 */ +#define RT3290_CFG0_DEF (0x59 << 24) + +/* possible flags for register RT3290_PLL_CTRL */ +#define RT3290_PLL_CONTROL (7 << 16) + +/* possible flags for register RT3290_WLAN_CTRL */ +#define RT3290_WLAN_EN (1U << 0) +#define RT3290_WLAN_CLK_EN (1U << 1) +#define RT3290_WLAN_RSV1 (1U << 2) +#define RT3290_WLAN_RESET (1U << 3) +#define RT3290_PCIE_APP0_CLK_REQ (1U << 4) +#define RT3290_FRC_WL_ANT_SET (1U << 5) +#define RT3290_INV_TR_SW0 (1U << 6) +#define RT3290_RADIO_EN (1U << 8) +#define RT3290_GPIO_IN_ALL (0xff << 8) +#define RT3290_GPIO_OUT_ALL (0xff << 16) +#define RT3290_GPIO_OUT_OE_ALL (0xff << 24) + /* possible flags for registers INT_STATUS/INT_MASK */ #define RT2860_TX_COHERENT (1 << 17) #define RT2860_RX_COHERENT (1 << 16) @@ -925,6 +972,7 @@ struct rt2860_rxwi { #define RT3070_RF_3320 0x000b /* 1T1R */ #define RT3070_RF_3053 0x000d /* dual-band 3T3R */ #define RT5592_RF_5592 0x000f /* dual-band 2T2R */ +#define RT3290_RF_3290 0x3290 /* 1T1R */ #define RT5390_RF_5360 0x5360 /* 1T1R */ #define RT5390_RF_5370 0x5370 /* 1T1R */ #define RT5390_RF_5372 0x5372 /* 2T2R */ @@ -1169,6 +1217,24 @@ static const struct rt2860_rate { { 105, 0x05 }, \ { 106, 0x35 } +#define RT3290_DEF_BBP \ + { 31, 0x08 }, \ + { 68, 0x0b }, \ + { 73, 0x13 }, \ + { 75, 0x46 }, \ + { 76, 0x28 }, \ + { 77, 0x59 }, \ + { 82, 0x62 }, \ + { 83, 0x7a }, \ + { 84, 0x9a }, \ + { 86, 0x38 }, \ + { 91, 0x04 }, \ + { 103, 0xc0 }, \ + { 104, 0x92 }, \ + { 105, 0x3c }, \ + { 106, 0x03 }, \ + { 128, 0x12 } + #define RT5390_DEF_BBP \ { 31, 0x08 }, \ { 65, 0x2c }, \ @@ -1469,6 +1535,53 @@ static const struct rt2860_rate { { 25, 0x01 }, \ { 29, 0x1f } +#define RT3290_DEF_RF \ + { 1, 0x0f }, \ + { 2, 0x80 }, \ + { 3, 0x08 }, \ + { 4, 0x00 }, \ + { 6, 0xa0 }, \ + { 8, 0xf3 }, \ + { 9, 0x02 }, \ + { 10, 0x53 }, \ + { 11, 0x4a }, \ + { 12, 0x46 }, \ + { 13, 0x9f }, \ + { 18, 0x03 }, \ + { 22, 0x20 }, \ + { 25, 0x80 }, \ + { 27, 0x09 }, \ + { 29, 0x10 }, \ + { 30, 0x10 }, \ + { 31, 0x80 }, \ + { 32, 0x80 }, \ + { 33, 0x00 }, \ + { 34, 0x05 }, \ + { 35, 0x12 }, \ + { 36, 0x00 }, \ + { 38, 0x85 }, \ + { 39, 0x1b }, \ + { 40, 0x0b }, \ + { 41, 0xbb }, \ + { 42, 0xd5 }, \ + { 43, 0x7b }, \ + { 44, 0x0e }, \ + { 45, 0xa2 }, \ + { 46, 0x73 }, \ + { 47, 0x00 }, \ + { 48, 0x10 }, \ + { 49, 0x98 }, \ + { 52, 0x38 }, \ + { 53, 0x00 }, \ + { 54, 0x78 }, \ + { 55, 0x43 }, \ + { 56, 0x02 }, \ + { 57, 0x80 }, \ + { 58, 0x7f }, \ + { 59, 0x09 }, \ + { 60, 0x45 }, \ + { 61, 0xc1 } + #define RT3572_DEF_RF \ { 0, 0x70 }, \ { 1, 0x81 }, \ |