diff --git a/sys/dev/rtwn/rtl8812a/r12a_reg.h b/sys/dev/rtwn/rtl8812a/r12a_reg.h index f1fc4ee2f302..c9a51c197acd 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_reg.h +++ b/sys/dev/rtwn/rtl8812a/r12a_reg.h @@ -34,6 +34,7 @@ */ /* System Configuration. */ #define R12A_SDIO_CTRL 0x070 +#define R12A_OPT_CTRL 0x074 #define R12A_RF_B_CTRL 0x076 /* Rx DMA Configuration. */ #define R12A_RXDMA_PRO 0x290 diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c index b6850eb9fa23..17f5388ff3a7 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c @@ -105,6 +105,86 @@ r12au_postattach(struct rtwn_softc *sc) sc->sc_ic.ic_ioctl = r12a_ioctl_net; } +/* + * These are inspired from github.com/aircrack-ng/rtl8812au/ in usb_halinit.c + */ + +void r12a_switch_to_usb3(struct rtwn_softc *sc); +void r12a_switch_to_usb2(struct rtwn_softc *sc); + +void +r12a_switch_to_usb3(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + uint8_t val8; + + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_HIGH) { + val8 = rtwn_read_1(sc, R12A_OPT_CTRL); /* 0x70 */ + device_printf(sc->sc_dev, "%s: 0x74 was 0x%x\n", + __func__, val8); + /* + * Check if it's already enabled; if so we leave things alone + * to avoid being stuck in a reprobe loop. + */ + if ((val8 & 0x0c) == 0x08) { + return; + } + rtwn_write_1(sc, R12A_OPT_CTRL, 0x8); /* 0x74 */ + rtwn_write_1(sc, R12A_SDIO_CTRL, 0x2); /* 0x70 */ + rtwn_write_1(sc, R92C_ACLK_MON, 0x1); /* 0x3e */ + rtwn_write_1(sc, 0x3d, 0x3); + + /* usb disconnect */ + rtwn_write_1(sc, R92C_APS_FSMCO + 1, 0x80); + /* 0x05 - high byte of FSMCO */ + } + + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_SUPER) { + val8 = rtwn_read_1(sc, 0x70); + val8 &= 0x02; /* bit 1 */ + rtwn_write_1(sc, 0x70, val8); + + val8 = rtwn_read_1(sc, 0x3e); + val8 &= 0x1; /* bit 0 */ + rtwn_write_1(sc, 0x3e, val8); + } +} + +void +r12a_switch_to_usb2(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + uint8_t val8; + + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_SUPER) { + val8 = rtwn_read_1(sc, R12A_OPT_CTRL); /* 0x70 */ + device_printf(sc->sc_dev, "%s: 0x74 was 0x%x\n", + __func__, val8); + + if ((val8 & 0x0c) == 0x04) { + return; + } + rtwn_write_1(sc, R12A_OPT_CTRL, 0x4); /* 0x74 */ + rtwn_write_1(sc, R12A_SDIO_CTRL, 0x2); /* 0x70 */ + rtwn_write_1(sc, R92C_ACLK_MON, 0x1); /* 0x3e */ + rtwn_write_1(sc, 0x3d, 0x3); + + /* usb disconnect */ + rtwn_write_1(sc, R92C_APS_FSMCO + 1, 0x80); + /* 0x05 - high byte of FSMCO */ + } + + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_HIGH) { + val8 = rtwn_read_1(sc, 0x70); + val8 &= 0x02; /* bit 1 */ + rtwn_write_1(sc, 0x70, val8); + + val8 = rtwn_read_1(sc, 0x3e); + val8 &= 0x1; /* bit 0 */ + rtwn_write_1(sc, 0x3e, val8); + } +} + void r12a_vap_preattach(struct rtwn_softc *sc, struct ieee80211vap *vap) { diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.c b/sys/dev/rtwn/usb/rtwn_usb_attach.c index 4958939a768a..57c14856759c 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_attach.c +++ b/sys/dev/rtwn/usb/rtwn_usb_attach.c @@ -379,6 +379,8 @@ rtwn_usb_sysctlattach(struct rtwn_softc *sc) uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MAX; } +extern void r12a_switch_to_usb3(struct rtwn_softc *sc); + static int rtwn_usb_attach(device_t self) { @@ -401,6 +403,22 @@ rtwn_usb_attach(device_t self) rtwn_usb_attach_methods(sc); rtwn_usb_attach_private(uc, USB_GET_DRIVER_INFO(uaa)); + /* Temp hack - see if we're RTL8812AU in USB2 or USB3 mode */ + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_SUPER) { + device_printf(sc->sc_dev, "%s: SUPER speed\n", __func__); + } + else if (usbd_get_speed(uc->uc_udev) == USB_SPEED_HIGH) { + device_printf(sc->sc_dev, "%s: HIGH speed\n", __func__); + RTWN_LOCK(sc); + r12a_switch_to_usb3(sc); + RTWN_UNLOCK(sc); + //error = ENXIO; + //goto detach; + } else + device_printf(sc->sc_dev, + "%s: .. unknown usb speed (%d)\n", __func__, + usbd_get_speed(uc->uc_udev)); + error = rtwn_usb_setup_endpoints(uc); if (error != 0) goto detach;