diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c index d7f110dd2bca..98dac91416dc 100644 --- a/sys/dev/usb/net/if_axe.c +++ b/sys/dev/usb/net/if_axe.c @@ -142,11 +142,11 @@ static const struct usb_device_id axe_devs[] = { AXE_DEV(ASIX, AX88172, 0), AXE_DEV(ASIX, AX88178, AXE_FLAG_178), AXE_DEV(ASIX, AX88772, AXE_FLAG_772), - AXE_DEV(ASIX, AX88772A, AXE_FLAG_772), + AXE_DEV(ASIX, AX88772A, AXE_FLAG_772A), AXE_DEV(ATEN, UC210T, 0), AXE_DEV(BELKIN, F5D5055, AXE_FLAG_178), AXE_DEV(BILLIONTON, USB2AR, 0), - AXE_DEV(CISCOLINKSYS, USB200MV2, AXE_FLAG_772), + AXE_DEV(CISCOLINKSYS, USB200MV2, AXE_FLAG_772A), AXE_DEV(COREGA, FETHER_USB2_TX, 0), AXE_DEV(DLINK, DUBE100, 0), AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772), @@ -191,6 +191,7 @@ static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *); static int axe_cmd(struct axe_softc *, int, int, int, void *); static void axe_ax88178_init(struct axe_softc *); static void axe_ax88772_init(struct axe_softc *); +static void axe_ax88772a_init(struct axe_softc *); static int axe_get_phyno(struct axe_softc *, int); static const struct usb_config axe_config[AXE_N_TRANSFER] = { @@ -613,7 +614,6 @@ axe_ax88178_init(struct axe_softc *sc) axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); } -#undef AXE_GPIO_WRITE static void axe_ax88772_init(struct axe_softc *sc) @@ -656,6 +656,47 @@ axe_ax88772_init(struct axe_softc *sc) axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); } +static void +axe_ax88772a_init(struct axe_softc *sc) +{ + struct usb_ether *ue; + uint16_t eeprom; + + ue = &sc->sc_ue; + axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom); + eeprom = le16toh(eeprom); + /* Reload EEPROM. */ + AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32); + if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) { + /* Manually select internal(embedded) PHY - MAC mode. */ + axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB | + AXE_SW_PHY_SELECT_EMBEDDED | AXE_SW_PHY_SELECT_SS_MII, + NULL); + uether_pause(&sc->sc_ue, hz / 32); + } else { + /* + * Manually select external PHY - MAC mode. + * Reverse MII/RMII is for AX88772A PHY mode. + */ + axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB | + AXE_SW_PHY_SELECT_EXT | AXE_SW_PHY_SELECT_SS_MII, NULL); + uether_pause(&sc->sc_ue, hz / 32); + } + /* Take PHY out of power down. */ + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPPD | + AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz / 4); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); + uether_pause(&sc->sc_ue, hz / 32); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz / 32); + axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); +} + +#undef AXE_GPIO_WRITE + static void axe_reset(struct axe_softc *sc) { @@ -677,6 +718,8 @@ axe_reset(struct axe_softc *sc) axe_ax88178_init(sc); else if (sc->sc_flags & AXE_FLAG_772) axe_ax88772_init(sc); + else if (sc->sc_flags & AXE_FLAG_772A) + axe_ax88772a_init(sc); } static void @@ -706,6 +749,9 @@ axe_attach_post(struct usb_ether *ue) } else if (sc->sc_flags & AXE_FLAG_772) { axe_ax88772_init(sc); sc->sc_tx_bufsz = 8 * 1024; + } else if (sc->sc_flags & AXE_FLAG_772A) { + axe_ax88772a_init(sc); + sc->sc_tx_bufsz = 8 * 1024; } /* @@ -719,7 +765,13 @@ axe_attach_post(struct usb_ether *ue) /* * Fetch IPG values. */ - axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs); + if (sc->sc_flags & AXE_FLAG_772A) { + /* Set IPG values. */ + sc->sc_ipgs[0] = 0x15; + sc->sc_ipgs[1] = 0x16; + sc->sc_ipgs[2] = 0x1A; + } else + axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs); } /* diff --git a/sys/dev/usb/net/if_axereg.h b/sys/dev/usb/net/if_axereg.h index 114d644b40d6..677291187535 100644 --- a/sys/dev/usb/net/if_axereg.h +++ b/sys/dev/usb/net/if_axereg.h @@ -92,6 +92,10 @@ #define AXE_CMD_SW_PHY_STATUS 0x0021 #define AXE_CMD_SW_PHY_SELECT 0x0122 +/* AX88772A and AX88772B only. */ +#define AXE_CMD_READ_VLAN_CTRL 0x4027 +#define AXE_CMD_WRITE_VLAN_CTRL 0x4028 + #define AXE_SW_RESET_CLEAR 0x00 #define AXE_SW_RESET_RR 0x01 #define AXE_SW_RESET_RT 0x02 @@ -172,6 +176,21 @@ #define AXE_PHY_MODE_REALTEK_8251CL 0x0E #define AXE_PHY_MODE_ATTANSIC 0x40 +/* AX88772A only. */ +#define AXE_SW_PHY_SELECT_EXT 0x0000 +#define AXE_SW_PHY_SELECT_EMBEDDED 0x0001 +#define AXE_SW_PHY_SELECT_AUTO 0x0002 +#define AXE_SW_PHY_SELECT_SS_MII 0x0004 +#define AXE_SW_PHY_SELECT_SS_RVRS_MII 0x0008 +#define AXE_SW_PHY_SELECT_SS_RVRS_RMII 0x000C +#define AXE_SW_PHY_SELECT_SS_ENB 0x0010 + +/* AX88772A/AX88772B VLAN control. */ +#define AXE_VLAN_CTRL_ENB 0x00001000 +#define AXE_VLAN_CTRL_STRIP 0x00002000 +#define AXE_VLAN_CTRL_VID1_MASK 0x00000FFF +#define AXE_VLAN_CTRL_VID2_MASK 0x0FFF0000 + #define AXE_BULK_BUF_SIZE 16384 /* bytes */ #define AXE_CTL_READ 0x01