From 74f934a14e8d0bead8086433596745e7c2b67990 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 10 Jul 2017 12:38:39 +0100 Subject: [PATCH] [smscusb] Allow for alternative PHY register layouts The LAN78xx PHY interrupt source and mask registers do not match those used by the SMSC75xx and SMSC95xx. Signed-off-by: Michael Brown --- src/drivers/net/smsc75xx.c | 7 +++++-- src/drivers/net/smsc75xx.h | 12 ++++++++++++ src/drivers/net/smsc95xx.c | 7 +++++-- src/drivers/net/smsc95xx.h | 12 ++++++++++++ src/drivers/net/smscusb.c | 13 +++++++------ src/drivers/net/smscusb.h | 22 ++++++++-------------- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/drivers/net/smsc75xx.c b/src/drivers/net/smsc75xx.c index c04dc1a7..0da255c2 100644 --- a/src/drivers/net/smsc75xx.c +++ b/src/drivers/net/smsc75xx.c @@ -350,7 +350,9 @@ static int smsc75xx_open ( struct net_device *netdev ) { goto err_set_filter; /* Enable PHY interrupts and update link status */ - if ( ( rc = smscusb_mii_open ( smscusb ) ) != 0 ) + if ( ( rc = smscusb_mii_open ( smscusb, SMSC75XX_MII_PHY_INTR_MASK, + ( SMSC75XX_PHY_INTR_ANEG_DONE | + SMSC75XX_PHY_INTR_LINK_DOWN ) ) ) != 0) goto err_mii_open; return 0; @@ -497,7 +499,8 @@ static int smsc75xx_probe ( struct usb_function *func, smscusb = netdev->priv; memset ( smscusb, 0, sizeof ( *smscusb ) ); smscusb_init ( smscusb, netdev, func, &smsc75xx_in_operations ); - smscusb_mii_init ( smscusb, SMSC75XX_MII_BASE ); + smscusb_mii_init ( smscusb, SMSC75XX_MII_BASE, + SMSC75XX_MII_PHY_INTR_SOURCE ); usb_refill_init ( &smscusb->usbnet.in, 0, SMSC75XX_IN_MTU, SMSC75XX_IN_MAX_FILL ); DBGC ( smscusb, "SMSC75XX %p on %s\n", smscusb, func->name ); diff --git a/src/drivers/net/smsc75xx.h b/src/drivers/net/smsc75xx.h index 0a330fd9..f8bcefb7 100644 --- a/src/drivers/net/smsc75xx.h +++ b/src/drivers/net/smsc75xx.h @@ -66,6 +66,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** MII register base */ #define SMSC75XX_MII_BASE 0x120 +/** PHY interrupt source MII register */ +#define SMSC75XX_MII_PHY_INTR_SOURCE 29 + +/** PHY interrupt mask MII register */ +#define SMSC75XX_MII_PHY_INTR_MASK 30 + +/** PHY interrupt: auto-negotiation complete */ +#define SMSC75XX_PHY_INTR_ANEG_DONE 0x0040 + +/** PHY interrupt: link down */ +#define SMSC75XX_PHY_INTR_LINK_DOWN 0x0010 + /** MAC address perfect filter register base */ #define SMSC75XX_ADDR_FILT_BASE 0x300 diff --git a/src/drivers/net/smsc95xx.c b/src/drivers/net/smsc95xx.c index e56cf5b4..9b09657d 100644 --- a/src/drivers/net/smsc95xx.c +++ b/src/drivers/net/smsc95xx.c @@ -462,7 +462,9 @@ static int smsc95xx_open ( struct net_device *netdev ) { goto err_set_address; /* Enable PHY interrupts and update link status */ - if ( ( rc = smscusb_mii_open ( smscusb ) ) != 0 ) + if ( ( rc = smscusb_mii_open ( smscusb, SMSC95XX_MII_PHY_INTR_MASK, + ( SMSC95XX_PHY_INTR_ANEG_DONE | + SMSC95XX_PHY_INTR_LINK_DOWN ) ) ) != 0) goto err_mii_open; return 0; @@ -606,7 +608,8 @@ static int smsc95xx_probe ( struct usb_function *func, smscusb = netdev->priv; memset ( smscusb, 0, sizeof ( *smscusb ) ); smscusb_init ( smscusb, netdev, func, &smsc95xx_in_operations ); - smscusb_mii_init ( smscusb, SMSC95XX_MII_BASE ); + smscusb_mii_init ( smscusb, SMSC95XX_MII_BASE, + SMSC95XX_MII_PHY_INTR_SOURCE ); usb_refill_init ( &smscusb->usbnet.in, ( sizeof ( struct smsc95xx_tx_header ) - sizeof ( struct smsc95xx_rx_header ) ), diff --git a/src/drivers/net/smsc95xx.h b/src/drivers/net/smsc95xx.h index b0ecf6ee..0cdf3824 100644 --- a/src/drivers/net/smsc95xx.h +++ b/src/drivers/net/smsc95xx.h @@ -65,6 +65,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** MII register base */ #define SMSC95XX_MII_BASE 0x0114 +/** PHY interrupt source MII register */ +#define SMSC95XX_MII_PHY_INTR_SOURCE 29 + +/** PHY interrupt mask MII register */ +#define SMSC95XX_MII_PHY_INTR_MASK 30 + +/** PHY interrupt: auto-negotiation complete */ +#define SMSC95XX_PHY_INTR_ANEG_DONE 0x0040 + +/** PHY interrupt: link down */ +#define SMSC95XX_PHY_INTR_LINK_DOWN 0x0010 + /** Receive packet header */ struct smsc95xx_rx_header { /** Command word */ diff --git a/src/drivers/net/smscusb.c b/src/drivers/net/smscusb.c index 19a679c4..60390ce3 100644 --- a/src/drivers/net/smscusb.c +++ b/src/drivers/net/smscusb.c @@ -578,7 +578,7 @@ int smscusb_mii_check_link ( struct smscusb_device *smscusb ) { int rc; /* Read PHY interrupt source */ - intr = mii_read ( &smscusb->mii, SMSCUSB_MII_PHY_INTR_SOURCE ); + intr = mii_read ( &smscusb->mii, smscusb->phy_source ); if ( intr < 0 ) { rc = intr; DBGC ( smscusb, "SMSCUSB %p could not get PHY interrupt " @@ -587,7 +587,7 @@ int smscusb_mii_check_link ( struct smscusb_device *smscusb ) { } /* Acknowledge PHY interrupt */ - if ( ( rc = mii_write ( &smscusb->mii, SMSCUSB_MII_PHY_INTR_SOURCE, + if ( ( rc = mii_write ( &smscusb->mii, smscusb->phy_source, intr ) ) != 0 ) { DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY " "interrupt: %s\n", smscusb, strerror ( rc ) ); @@ -610,15 +610,16 @@ int smscusb_mii_check_link ( struct smscusb_device *smscusb ) { * Enable PHY interrupts and update link status * * @v smscusb SMSC USB device + * @v phy_mask PHY interrupt mask register + * @v intrs PHY interrupts to enable * @ret rc Return status code */ -int smscusb_mii_open ( struct smscusb_device *smscusb ) { +int smscusb_mii_open ( struct smscusb_device *smscusb, + unsigned int phy_mask, unsigned int intrs ) { int rc; /* Enable PHY interrupts */ - if ( ( rc = mii_write ( &smscusb->mii, SMSCUSB_MII_PHY_INTR_MASK, - ( SMSCUSB_PHY_INTR_ANEG_DONE | - SMSCUSB_PHY_INTR_LINK_DOWN ) ) ) != 0 ) { + if ( ( rc = mii_write ( &smscusb->mii, phy_mask, intrs ) ) != 0 ) { DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt " "mask: %s\n", smscusb, strerror ( rc ) ); return rc; diff --git a/src/drivers/net/smscusb.h b/src/drivers/net/smscusb.h index d7216d9a..5e4440ea 100644 --- a/src/drivers/net/smscusb.h +++ b/src/drivers/net/smscusb.h @@ -105,18 +105,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define SMSCUSB_MII_DATA_GET(mii_data) \ ( ( (mii_data) >> 0 ) & 0xffff ) /**< Get data */ -/** PHY interrupt source MII register */ -#define SMSCUSB_MII_PHY_INTR_SOURCE 29 - -/** PHY interrupt mask MII register */ -#define SMSCUSB_MII_PHY_INTR_MASK 30 - -/** PHY interrupt: auto-negotiation complete */ -#define SMSCUSB_PHY_INTR_ANEG_DONE 0x0040 - -/** PHY interrupt: link down */ -#define SMSCUSB_PHY_INTR_LINK_DOWN 0x0010 - /** Maximum time to wait for MII (in milliseconds) */ #define SMSCUSB_MII_MAX_WAIT_MS 100 @@ -166,6 +154,8 @@ struct smscusb_device { struct mii_interface mii; /** MII register base */ uint16_t mii_base; + /** PHY interrupt source register */ + uint16_t phy_source; /** Interrupt status */ uint32_t int_sts; }; @@ -279,12 +269,15 @@ smscusb_init ( struct smscusb_device *smscusb, struct net_device *netdev, * * @v smscusb SMSC USB device * @v mii_base MII register base + * @v phy_source Interrupt source PHY register */ static inline __attribute__ (( always_inline )) void -smscusb_mii_init ( struct smscusb_device *smscusb, unsigned int mii_base ) { +smscusb_mii_init ( struct smscusb_device *smscusb, unsigned int mii_base, + unsigned int phy_source ) { mii_init ( &smscusb->mii, &smscusb_mii_operations ); smscusb->mii_base = mii_base; + smscusb->phy_source = phy_source; } extern int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb, @@ -292,7 +285,8 @@ extern int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb, extern int smscusb_otp_fetch_mac ( struct smscusb_device *smscusb, unsigned int otp_base ); extern int smscusb_mii_check_link ( struct smscusb_device *smscusb ); -extern int smscusb_mii_open ( struct smscusb_device *smscusb ); +extern int smscusb_mii_open ( struct smscusb_device *smscusb, + unsigned int phy_mask, unsigned int intrs ); extern int smscusb_set_address ( struct smscusb_device *smscusb, unsigned int addr_base ); extern int smscusb_set_filter ( struct smscusb_device *smscusb,