diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-11 13:40:47 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-11 13:40:47 +0000 |
commit | 0f8365d463f750dcfdb032070f4fe8818dbb95a7 (patch) | |
tree | c782b1ca1b424d800b4d8c416ad9bfb59473ad0f /sys/dev | |
parent | 3db44835013f5fbe990c41bc7a6ebd216f9e9ac4 (diff) |
Add support for RTL8153 devices. Heavily based on changes made by Kevin Lo
to the FreeBSD driver.
This driver will attach instead of cdce(4), which doesn't expose a PHY and
doesn't work with my 5c20 revision of the chip.
ok jimatthew@, jcs@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/mii/rgephy.c | 8 | ||||
-rw-r--r-- | sys/dev/usb/if_ure.c | 266 | ||||
-rw-r--r-- | sys/dev/usb/if_urereg.h | 10 |
3 files changed, 250 insertions, 34 deletions
diff --git a/sys/dev/mii/rgephy.c b/sys/dev/mii/rgephy.c index ab0e7c7c687..b4c95d078fa 100644 --- a/sys/dev/mii/rgephy.c +++ b/sys/dev/mii/rgephy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rgephy.c,v 1.38 2015/07/19 06:35:18 yuo Exp $ */ +/* $OpenBSD: rgephy.c,v 1.39 2017/03/11 13:40:46 kettenis Exp $ */ /* * Copyright (c) 2003 * Bill Paul <wpaul@windriver.com>. All rights reserved. @@ -249,7 +249,7 @@ setit: * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. */ - if (strcmp(devname, "re") == 0) { + if (strcmp(devname, "re") == 0 || strcmp(devname, "ure") == 0) { reg = PHY_READ(sc, RL_GMEDIASTAT); if (reg & RL_GMEDIASTAT_LINK) { sc->mii_ticks = 0; @@ -305,7 +305,7 @@ rgephy_status(struct mii_softc *sc) mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - if (strcmp(devname, "re") == 0) { + if (strcmp(devname, "re") == 0 || strcmp(devname, "ure") == 0) { bmsr = PHY_READ(sc, RL_GMEDIASTAT); if (bmsr & RL_GMEDIASTAT_LINK) mii->mii_media_status |= IFM_ACTIVE; @@ -330,7 +330,7 @@ rgephy_status(struct mii_softc *sc) } } - if (strcmp(devname, "re") == 0) { + if (strcmp(devname, "re") == 0 || strcmp(devname, "ure") == 0) { bmsr = PHY_READ(sc, RL_GMEDIASTAT); if (bmsr & RL_GMEDIASTAT_1000MBPS) mii->mii_media_active |= IFM_1000_T; diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 5e6ec3a659a..a9b6b480d12 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -1,6 +1,6 @@ -/* $OpenBSD: if_ure.c,v 1.3 2017/01/22 10:17:39 dlg Exp $ */ +/* $OpenBSD: if_ure.c,v 1.4 2017/03/11 13:40:46 kettenis Exp $ */ /*- - * Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org> + * Copyright (c) 2015-2016 Kevin Lo <kevlo@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,7 +58,8 @@ #include <dev/usb/usbdivar.h> #include <dev/usb/usbdevs.h> -#include "if_urereg.h" +#include <dev/ic/rtl81x9reg.h> +#include <dev/usb/if_urereg.h> #ifdef URE_DEBUG #define DPRINTF(x) do { if (uredebug) printf x; } while (0) @@ -69,9 +70,9 @@ int uredebug = 0; #define DPRINTFN(n,x) #endif - const struct usb_devno ure_devs[] = { - { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152 } + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152 }, + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8153 } }; int ure_match(struct device *, void *, void *); @@ -126,6 +127,7 @@ int ure_ifmedia_upd(struct ifnet *); void ure_ifmedia_sts(struct ifnet *, struct ifmediareq *); int ure_ioctl(struct ifnet *, u_long, caddr_t); void ure_rtl8152_init(struct ure_softc *); +void ure_rtl8153_init(struct ure_softc *); void ure_disable_teredo(struct ure_softc *); void ure_init_fifo(struct ure_softc *); @@ -302,6 +304,10 @@ ure_miibus_readreg(struct device *dev, int phy, int reg) if (usbd_is_dying(sc->ure_udev)) return 0; + /* Let the rgephy driver read the URE_PLA_PHYSTATUS register. */ + if (reg == RL_GMEDIASTAT) + return ure_read_1(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA); + ure_lock_mii(sc); val = ure_ocp_reg_read(sc, URE_OCP_BASE_MII + reg * 2); ure_unlock_mii(sc); @@ -337,6 +343,11 @@ ure_miibus_statchg(struct device *dev) case IFM_100_TX: sc->ure_flags |= URE_FLAG_LINK; break; + case IFM_1000_T: + if ((sc->ure_flags & URE_FLAG_8152) != 0) + break; + sc->ure_flags |= URE_FLAG_LINK; + break; default: break; } @@ -389,7 +400,9 @@ ure_iff(struct ure_softc *sc) return; ifp->if_flags &= ~IFF_ALLMULTI; - rxmode = ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA); + rxmode = URE_RCR_APM; + if (ifp->if_flags & IFF_BROADCAST) + rxmode |= URE_RCR_AB; if (ifp->if_flags & IFF_PROMISC || sc->ure_ac.ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; if (ifp->if_flags & IFF_PROMISC) @@ -443,7 +456,6 @@ ure_init(void *xsc) struct ure_softc *sc = xsc; struct ure_chain *c; struct ifnet *ifp = &sc->ure_ac.ac_if; - uint32_t rxmode; usbd_status err; int s, i; @@ -487,18 +499,6 @@ ure_init(void *xsc) ure_read_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) & ~URE_RXDY_GATED_EN); - /* Set Rx mode. */ - rxmode = URE_RCR_APM; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxmode |= URE_RCR_AAP; - - if (ifp->if_flags & IFF_BROADCAST) - rxmode |= URE_RCR_AB; - - ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode); - /* Load the multicast filter. */ ure_iff(sc); @@ -697,6 +697,156 @@ ure_rtl8152_init(struct ure_softc *sc) } void +ure_rtl8153_init(struct ure_softc *sc) +{ + uint16_t val; + uint8_t u1u2[8]; + int i; + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); + usbd_delay_ms(sc->ure_udev, 20); + + memset(u1u2, 0x00, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + for (i = 0; i < URE_TIMEOUT; i++) { + if (ure_read_2(sc, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) & + URE_AUTOLOAD_DONE) + break; + usbd_delay_ms(sc->ure_udev, 10); + } + if (i == URE_TIMEOUT) + printf("%s: timeout waiting for chip autoload\n", + sc->ure_dev.dv_xname); + + for (i = 0; i < URE_TIMEOUT; i++) { + val = ure_ocp_reg_read(sc, URE_OCP_PHY_STATUS) & + URE_PHY_STAT_MASK; + if (val == URE_PHY_STAT_LAN_ON || val == URE_PHY_STAT_PWRDN) + break; + usbd_delay_ms(sc->ure_udev, 10); + } + if (i == URE_TIMEOUT) + printf("%s: timeout waiting for phy to stabilize\n", + sc->ure_dev.dv_xname); + + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB) & + ~URE_U2P3_ENABLE); + + if (sc->ure_chip & URE_CHIP_VER_5C10) { + val = ure_read_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB); + val &= ~URE_PWD_DN_SCALE_MASK; + val |= URE_PWD_DN_SCALE(96); + ure_write_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB, val); + + ure_write_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB, + ure_read_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB) | + URE_USB2PHY_L1 | URE_USB2PHY_SUSPEND); + } else if (sc->ure_chip & URE_CHIP_VER_5C20) { + ure_write_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA, + ure_read_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA) & + ~URE_ECM_ALDPS); + } + if (sc->ure_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) { + val = ure_read_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB); + if (ure_read_2(sc, URE_USB_BURST_SIZE, URE_MCU_TYPE_USB) == + 0) + val &= ~URE_DYNAMIC_BURST; + else + val |= URE_DYNAMIC_BURST; + ure_write_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB, val); + } + + ure_write_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB, + ure_read_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB) | + URE_EP4_FULL_FC); + + ure_write_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB) & + ~URE_TIMER11_EN); + + ure_write_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA) & + ~URE_LED_MODE_MASK); + + if ((sc->ure_chip & URE_CHIP_VER_5C10) && + sc->ure_udev->speed != USB_SPEED_SUPER) + val = URE_LPM_TIMER_500MS; + else + val = URE_LPM_TIMER_500US; + ure_write_1(sc, URE_USB_LPM_CTRL, URE_MCU_TYPE_USB, + val | URE_FIFO_EMPTY_1FB | URE_ROK_EXIT_LPM); + + val = ure_read_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB); + val &= ~URE_SEN_VAL_MASK; + val |= URE_SEN_VAL_NORMAL | URE_SEL_RXIDLE; + ure_write_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB, val); + + ure_write_2(sc, URE_USB_CONNECT_TIMER, URE_MCU_TYPE_USB, 0x0001); + + ure_write_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB) & + ~(URE_PWR_EN | URE_PHASE2_EN)); + ure_write_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB) & + ~URE_PCUT_STATUS); + + memset(u1u2, 0xff, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, + URE_ALDPS_SPDWN_RATIO); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, + URE_EEE_SPDWN_RATIO); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, + URE_PKT_AVAIL_SPDWN_EN | URE_SUSPEND_SPDWN_EN | + URE_U1U2_SPDWN_EN | URE_L1_SPDWN_EN); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, + URE_PWRSAVE_SPDWN_EN | URE_RXDV_SPDWN_EN | URE_TX10MIDLE_EN | + URE_TP100_SPDWN_EN | URE_TP500_SPDWN_EN | URE_TP1000_SPDWN_EN | + URE_EEE_SPDWN_EN); + + val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); + if (!(sc->ure_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) + val |= URE_U2P3_ENABLE; + else + val &= ~URE_U2P3_ENABLE; + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); + + memset(u1u2, 0x00, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); + usbd_delay_ms(sc->ure_udev, 20); + + ure_init_fifo(sc); + + /* Disable Rx aggregation. */ + ure_write_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB) | + URE_RX_AGG_DISABLE); + + val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); + if (!(sc->ure_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) + val |= URE_U2P3_ENABLE; + else + val &= ~URE_U2P3_ENABLE; + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); + + memset(u1u2, 0xff, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); +} + +void ure_disable_teredo(struct ure_softc *sc) { ure_write_4(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, @@ -724,6 +874,43 @@ ure_init_fifo(struct ure_softc *sc) ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA) & ~URE_RCR_ACPT_ALL); + if (!(sc->ure_flags & URE_FLAG_8152)) { + if (sc->ure_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10 | + URE_CHIP_VER_5C20)) { + ure_ocp_reg_write(sc, URE_OCP_ADC_CFG, + URE_CKADSEL_L | URE_ADC_EN | URE_EN_EMI_L); + } + if (sc->ure_chip & URE_CHIP_VER_5C00) { + ure_ocp_reg_write(sc, URE_OCP_EEE_CFG, + ure_ocp_reg_read(sc, URE_OCP_EEE_CFG) & + ~URE_CTAP_SHORT_EN); + } + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | + URE_EEE_CLKDIV_EN); + ure_ocp_reg_write(sc, URE_OCP_DOWN_SPEED, + ure_ocp_reg_read(sc, URE_OCP_DOWN_SPEED) | + URE_EN_10M_BGOFF); + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | + URE_EN_10M_PLLOFF); + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_IMPEDANCE); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0b13); + ure_write_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA) | + URE_PFM_PWM_SWITCH); + + /* Enable LPF corner auto tune. */ + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_LPF_CFG); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0xf70f); + + /* Adjust 10M amplitude. */ + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP1); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x00af); + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP2); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0208); + } + ure_reset(sc); ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 0); @@ -742,7 +929,7 @@ ure_init_fifo(struct ure_softc *sc) usbd_delay_ms(sc->ure_udev, 10); } if (i == URE_TIMEOUT) - printf("%s timeout waiting for OOB control\n", + printf("%s: timeout waiting for OOB control\n", sc->ure_dev.dv_xname); ure_write_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, ure_read_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) | @@ -864,6 +1051,9 @@ ure_attach(struct device *parent, struct device *self, void *aux) sc->ure_udev = uaa->device; sc->ure_iface = uaa->iface; + if (uaa->product == USB_PRODUCT_REALTEK_RTL8152) + sc->ure_flags |= URE_FLAG_8152; + usb_init_task(&sc->ure_tick_task, ure_tick_task, sc, USB_TASK_TYPE_GENERIC); rw_init(&sc->ure_mii_lock, "uremii"); @@ -899,15 +1089,27 @@ ure_attach(struct device *parent, struct device *self, void *aux) switch (ver) { case 0x4c00: sc->ure_chip |= URE_CHIP_VER_4C00; - ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, eaddr, - sizeof(eaddr)); printf("ver 4c00"); break; case 0x4c10: sc->ure_chip |= URE_CHIP_VER_4C10; - ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, eaddr, - sizeof(eaddr)); - printf("ver 4c01"); + printf("ver 4c10"); + break; + case 0x5c00: + sc->ure_chip |= URE_CHIP_VER_5C00; + printf("ver 5c00"); + break; + case 0x5c10: + sc->ure_chip |= URE_CHIP_VER_5C10; + printf("ver 5c10"); + break; + case 0x5c20: + sc->ure_chip |= URE_CHIP_VER_5C20; + printf("ver 5c20"); + break; + case 0x5c30: + sc->ure_chip |= URE_CHIP_VER_5C30; + printf("ver 5c30"); break; default: printf(", unknown ver %02x", ver); @@ -915,12 +1117,22 @@ ure_attach(struct device *parent, struct device *self, void *aux) break; } + if (sc->ure_flags & URE_FLAG_8152) + ure_rtl8152_init(sc); + else + ure_rtl8153_init(sc); + + if (sc->ure_chip & URE_CHIP_VER_4C00) + ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, eaddr, + sizeof(eaddr)); + else + ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, eaddr, + sizeof(eaddr)); + printf(", address %s\n", ether_sprintf(eaddr)); bcopy(eaddr, (char *)&sc->ure_ac.ac_enaddr, ETHER_ADDR_LEN); - ure_rtl8152_init(sc); - ifp = &sc->ure_ac.ac_if; ifp->if_softc = sc; strlcpy(ifp->if_xname, sc->ure_dev.dv_xname, IFNAMSIZ); diff --git a/sys/dev/usb/if_urereg.h b/sys/dev/usb/if_urereg.h index 8f885c8cabf..2260ec37890 100644 --- a/sys/dev/usb/if_urereg.h +++ b/sys/dev/usb/if_urereg.h @@ -1,6 +1,6 @@ -/* $OpenBSD: if_urereg.h,v 1.2 2016/08/07 00:21:57 jmatthew Exp $ */ +/* $OpenBSD: if_urereg.h,v 1.3 2017/03/11 13:40:46 kettenis Exp $ */ /*- - * Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org> + * Copyright (c) 2015-2016 Kevin Lo <kevlo@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -462,9 +462,13 @@ struct ure_softc { u_int ure_flags; #define URE_FLAG_LINK 0x0001 +#define URE_FLAG_8152 0x1000 /* RTL8152 */ u_int ure_chip; #define URE_CHIP_VER_4C00 0x01 #define URE_CHIP_VER_4C10 0x02 +#define URE_CHIP_VER_5C00 0x04 +#define URE_CHIP_VER_5C10 0x08 +#define URE_CHIP_VER_5C20 0x10 +#define URE_CHIP_VER_5C30 0x20 }; - |