Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/usb/net/if_muge.c
Show First 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
struct muge_softc { | struct muge_softc { | ||||
struct usb_ether sc_ue; | struct usb_ether sc_ue; | ||||
struct mtx sc_mtx; | struct mtx sc_mtx; | ||||
struct usb_xfer *sc_xfer[MUGE_N_TRANSFER]; | struct usb_xfer *sc_xfer[MUGE_N_TRANSFER]; | ||||
int sc_phyno; | int sc_phyno; | ||||
uint32_t sc_leds; | uint32_t sc_leds; | ||||
uint16_t sc_led_modes; | |||||
uint16_t sc_led_modes_mask; | |||||
/* Settings for the mac control (MAC_CSR) register. */ | /* Settings for the mac control (MAC_CSR) register. */ | ||||
uint32_t sc_rfe_ctl; | uint32_t sc_rfe_ctl; | ||||
uint32_t sc_mdix_ctl; | uint32_t sc_mdix_ctl; | ||||
uint16_t chipid; | uint16_t chipid; | ||||
uint16_t chiprev; | uint16_t chiprev; | ||||
uint32_t sc_mchash_table[ETH_DP_SEL_VHF_HASH_LEN]; | uint32_t sc_mchash_table[ETH_DP_SEL_VHF_HASH_LEN]; | ||||
uint32_t sc_pfilter_table[MUGE_NUM_PFILTER_ADDRS_][2]; | uint32_t sc_pfilter_table[MUGE_NUM_PFILTER_ADDRS_][2]; | ||||
▲ Show 20 Lines • Show All 700 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* RETURNS: | * RETURNS: | ||||
* Returns 0 on success or EIO if failed to reset the PHY. | * Returns 0 on success or EIO if failed to reset the PHY. | ||||
*/ | */ | ||||
static int | static int | ||||
lan78xx_phy_init(struct muge_softc *sc) | lan78xx_phy_init(struct muge_softc *sc) | ||||
{ | { | ||||
muge_dbg_printf(sc, "Initializing PHY.\n"); | muge_dbg_printf(sc, "Initializing PHY.\n"); | ||||
uint16_t bmcr; | uint16_t bmcr, lmsr; | ||||
usb_ticks_t start_ticks; | usb_ticks_t start_ticks; | ||||
uint32_t hw_reg; | uint32_t hw_reg; | ||||
const usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000); | const usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000); | ||||
MUGE_LOCK_ASSERT(sc, MA_OWNED); | MUGE_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* Reset phy and wait for reset to complete. */ | /* Reset phy and wait for reset to complete. */ | ||||
lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, | lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, | ||||
Show All 27 Lines | lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_ANAR, | ||||
ANAR_CSMA | ANAR_FC | ANAR_PAUSE_ASYM); | ANAR_CSMA | ANAR_FC | ANAR_PAUSE_ASYM); | ||||
/* Restart auto-negotation. */ | /* Restart auto-negotation. */ | ||||
bmcr |= BMCR_STARTNEG; | bmcr |= BMCR_STARTNEG; | ||||
bmcr |= BMCR_AUTOEN; | bmcr |= BMCR_AUTOEN; | ||||
lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, bmcr); | lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, bmcr); | ||||
bmcr = lan78xx_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR); | bmcr = lan78xx_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR); | ||||
/* Configure LED Modes. */ | |||||
if (sc->sc_led_modes_mask != 0xffff) { | |||||
lmsr = lan78xx_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, | |||||
MUGE_PHY_LED_MODE); | |||||
lmsr &= sc->sc_led_modes_mask; | |||||
lmsr |= sc->sc_led_modes; | |||||
lan78xx_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, | |||||
MUGE_PHY_LED_MODE, lmsr); | |||||
} | |||||
/* Enable appropriate LEDs. */ | /* Enable appropriate LEDs. */ | ||||
if (sc->sc_leds != 0 && | if (sc->sc_leds != 0 && | ||||
lan78xx_read_reg(sc, ETH_HW_CFG, &hw_reg) == 0) { | lan78xx_read_reg(sc, ETH_HW_CFG, &hw_reg) == 0) { | ||||
hw_reg &= ~(ETH_HW_CFG_LEDO_EN_ | ETH_HW_CFG_LED1_EN_ | | hw_reg &= ~(ETH_HW_CFG_LEDO_EN_ | ETH_HW_CFG_LED1_EN_ | | ||||
ETH_HW_CFG_LED2_EN_ | ETH_HW_CFG_LED3_EN_ ); | ETH_HW_CFG_LED2_EN_ | ETH_HW_CFG_LED3_EN_ ); | ||||
hw_reg |= sc->sc_leds; | hw_reg |= sc->sc_leds; | ||||
lan78xx_write_reg(sc, ETH_HW_CFG, hw_reg); | lan78xx_write_reg(sc, ETH_HW_CFG, hw_reg); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | muge_fdt_find_mac(const char *compatible, unsigned char *mac) | ||||
node = muge_fdt_find_eth_node(root, compatible); | node = muge_fdt_find_eth_node(root, compatible); | ||||
if (node != -1) { | if (node != -1) { | ||||
if (muge_fdt_read_mac_property(node, mac) == 0) | if (muge_fdt_read_mac_property(node, mac) == 0) | ||||
return (0); | return (0); | ||||
} | } | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/** | |||||
* muge_fdt_count_led_modes - read number of LED modes from node | |||||
* @compatible: compatible string for DTB node in the form | |||||
* "usb[N]NNN,[M]MMM" | |||||
* where NNN is vendor id and MMM is product id | |||||
* @amount: memory to store number of LED entries to | |||||
* | |||||
* Tries to find matching node in DTS and obtain number of entries from it. | |||||
* | |||||
* RETURNS: | |||||
* Returns 0 on success, error code otherwise | |||||
*/ | |||||
static int | |||||
muge_fdt_count_led_modes(struct muge_softc *sc, const char *compatible, | |||||
uint32_t *amount) | |||||
{ | |||||
phandle_t node, root; | |||||
ssize_t proplen; | |||||
*amount = 0; | |||||
root = OF_finddevice("/"); | |||||
node = muge_fdt_find_eth_node(root, compatible); | |||||
if (node != -1 && | |||||
(proplen = OF_getproplen(node, "microchip,led-modes")) > 0) { | |||||
*amount = proplen / sizeof( uint32_t ); | |||||
return (0); | |||||
} | |||||
return (ENXIO); | |||||
} | |||||
#endif | #endif | ||||
/** | /** | ||||
* muge_set_mac_addr - Initiailizes NIC MAC address | * muge_set_mac_addr - Initiailizes NIC MAC address | ||||
* @ue: the USB ethernet device | * @ue: the USB ethernet device | ||||
* | * | ||||
* Tries to obtain MAC address from number of sources: registers, | * Tries to obtain MAC address from number of sources: registers, | ||||
* EEPROM, DTB blob. If all sources fail - generates random MAC. | * EEPROM, DTB blob. If all sources fail - generates random MAC. | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
muge_set_leds(struct usb_ether *ue) | muge_set_leds(struct usb_ether *ue) | ||||
{ | { | ||||
struct muge_softc *sc = uether_getsc(ue); | struct muge_softc *sc = uether_getsc(ue); | ||||
#ifdef FDT | #ifdef FDT | ||||
char compatible[16]; | char compatible[16]; | ||||
struct usb_attach_arg *uaa = device_get_ivars(ue->ue_dev); | struct usb_attach_arg *uaa = device_get_ivars(ue->ue_dev); | ||||
phandle_t root, node; | |||||
pcell_t led_modes[4]; /* 4 LEDs are possible */ | |||||
ssize_t proplen; | |||||
uint32_t count; | uint32_t count; | ||||
#endif | #endif | ||||
sc->sc_leds = 0; /* no LED mode is set */ | sc->sc_leds = 0; /* no LED mode is set */ | ||||
sc->sc_led_modes = 0; | |||||
sc->sc_led_modes_mask = 0xffff; | |||||
if (lan78xx_eeprom_present(sc)) | if (lan78xx_eeprom_present(sc)) | ||||
return; | return; | ||||
#ifdef FDT | #ifdef FDT | ||||
snprintf(compatible, sizeof(compatible), "usb%x,%x", | snprintf(compatible, sizeof(compatible), "usb%x,%x", | ||||
uaa->info.idVendor, uaa->info.idProduct); | uaa->info.idVendor, uaa->info.idProduct); | ||||
if (muge_fdt_count_led_modes(sc, compatible, &count) == 0) { | root = OF_finddevice("/"); | ||||
if ((node = muge_fdt_find_eth_node(root, compatible)) != -1 && | |||||
(proplen = OF_getencprop(node, "microchip,led-modes", led_modes, | |||||
sizeof(led_modes))) > 0) { | |||||
count = proplen / sizeof( uint32_t ); | |||||
sc->sc_leds = (count > 0) * ETH_HW_CFG_LEDO_EN_ | | sc->sc_leds = (count > 0) * ETH_HW_CFG_LEDO_EN_ | | ||||
(count > 1) * ETH_HW_CFG_LED1_EN_ | | (count > 1) * ETH_HW_CFG_LED1_EN_ | | ||||
(count > 2) * ETH_HW_CFG_LED2_EN_ | | (count > 2) * ETH_HW_CFG_LED2_EN_ | | ||||
(count > 3) * ETH_HW_CFG_LED3_EN_; | (count > 3) * ETH_HW_CFG_LED3_EN_; | ||||
while (count-- > 0) { | |||||
sc->sc_led_modes |= | |||||
(led_modes[count] & 0xf) << (4 * count); | |||||
sc->sc_led_modes_mask <<= 4; | |||||
} | |||||
muge_dbg_printf(sc, "LED modes set from FDT blob\n"); | muge_dbg_printf(sc, "LED modes set from FDT blob\n"); | ||||
return; | |||||
} | } | ||||
#endif | #endif | ||||
muge_dbg_printf(sc, "LED configuration not available\n"); | |||||
} | } | ||||
/** | /** | ||||
* muge_attach_post - Called after the driver attached to the USB interface | * muge_attach_post - Called after the driver attached to the USB interface | ||||
* @ue: the USB ethernet device | * @ue: the USB ethernet device | ||||
* | * | ||||
* This is where the chip is intialised for the first time. This is | * This is where the chip is intialised for the first time. This is | ||||
* different from the muge_init() function in that that one is designed to | * different from the muge_init() function in that that one is designed to | ||||
▲ Show 20 Lines • Show All 723 Lines • Show Last 20 Lines |