[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 <mcb30@ipxe.org>
This commit is contained in:
parent
340f03392d
commit
74f934a14e
|
@ -350,7 +350,9 @@ static int smsc75xx_open ( struct net_device *netdev ) {
|
||||||
goto err_set_filter;
|
goto err_set_filter;
|
||||||
|
|
||||||
/* Enable PHY interrupts and update link status */
|
/* 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;
|
goto err_mii_open;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -497,7 +499,8 @@ static int smsc75xx_probe ( struct usb_function *func,
|
||||||
smscusb = netdev->priv;
|
smscusb = netdev->priv;
|
||||||
memset ( smscusb, 0, sizeof ( *smscusb ) );
|
memset ( smscusb, 0, sizeof ( *smscusb ) );
|
||||||
smscusb_init ( smscusb, netdev, func, &smsc75xx_in_operations );
|
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,
|
usb_refill_init ( &smscusb->usbnet.in, 0, SMSC75XX_IN_MTU,
|
||||||
SMSC75XX_IN_MAX_FILL );
|
SMSC75XX_IN_MAX_FILL );
|
||||||
DBGC ( smscusb, "SMSC75XX %p on %s\n", smscusb, func->name );
|
DBGC ( smscusb, "SMSC75XX %p on %s\n", smscusb, func->name );
|
||||||
|
|
|
@ -66,6 +66,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
/** MII register base */
|
/** MII register base */
|
||||||
#define SMSC75XX_MII_BASE 0x120
|
#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 */
|
/** MAC address perfect filter register base */
|
||||||
#define SMSC75XX_ADDR_FILT_BASE 0x300
|
#define SMSC75XX_ADDR_FILT_BASE 0x300
|
||||||
|
|
||||||
|
|
|
@ -462,7 +462,9 @@ static int smsc95xx_open ( struct net_device *netdev ) {
|
||||||
goto err_set_address;
|
goto err_set_address;
|
||||||
|
|
||||||
/* Enable PHY interrupts and update link status */
|
/* 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;
|
goto err_mii_open;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -606,7 +608,8 @@ static int smsc95xx_probe ( struct usb_function *func,
|
||||||
smscusb = netdev->priv;
|
smscusb = netdev->priv;
|
||||||
memset ( smscusb, 0, sizeof ( *smscusb ) );
|
memset ( smscusb, 0, sizeof ( *smscusb ) );
|
||||||
smscusb_init ( smscusb, netdev, func, &smsc95xx_in_operations );
|
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,
|
usb_refill_init ( &smscusb->usbnet.in,
|
||||||
( sizeof ( struct smsc95xx_tx_header ) -
|
( sizeof ( struct smsc95xx_tx_header ) -
|
||||||
sizeof ( struct smsc95xx_rx_header ) ),
|
sizeof ( struct smsc95xx_rx_header ) ),
|
||||||
|
|
|
@ -65,6 +65,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
/** MII register base */
|
/** MII register base */
|
||||||
#define SMSC95XX_MII_BASE 0x0114
|
#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 */
|
/** Receive packet header */
|
||||||
struct smsc95xx_rx_header {
|
struct smsc95xx_rx_header {
|
||||||
/** Command word */
|
/** Command word */
|
||||||
|
|
|
@ -578,7 +578,7 @@ int smscusb_mii_check_link ( struct smscusb_device *smscusb ) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Read PHY interrupt source */
|
/* 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 ) {
|
if ( intr < 0 ) {
|
||||||
rc = intr;
|
rc = intr;
|
||||||
DBGC ( smscusb, "SMSCUSB %p could not get PHY interrupt "
|
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 */
|
/* 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 ) {
|
intr ) ) != 0 ) {
|
||||||
DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY "
|
DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY "
|
||||||
"interrupt: %s\n", smscusb, strerror ( rc ) );
|
"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
|
* Enable PHY interrupts and update link status
|
||||||
*
|
*
|
||||||
* @v smscusb SMSC USB device
|
* @v smscusb SMSC USB device
|
||||||
|
* @v phy_mask PHY interrupt mask register
|
||||||
|
* @v intrs PHY interrupts to enable
|
||||||
* @ret rc Return status code
|
* @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;
|
int rc;
|
||||||
|
|
||||||
/* Enable PHY interrupts */
|
/* Enable PHY interrupts */
|
||||||
if ( ( rc = mii_write ( &smscusb->mii, SMSCUSB_MII_PHY_INTR_MASK,
|
if ( ( rc = mii_write ( &smscusb->mii, phy_mask, intrs ) ) != 0 ) {
|
||||||
( SMSCUSB_PHY_INTR_ANEG_DONE |
|
|
||||||
SMSCUSB_PHY_INTR_LINK_DOWN ) ) ) != 0 ) {
|
|
||||||
DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt "
|
DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt "
|
||||||
"mask: %s\n", smscusb, strerror ( rc ) );
|
"mask: %s\n", smscusb, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -105,18 +105,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
#define SMSCUSB_MII_DATA_GET(mii_data) \
|
#define SMSCUSB_MII_DATA_GET(mii_data) \
|
||||||
( ( (mii_data) >> 0 ) & 0xffff ) /**< Get 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) */
|
/** Maximum time to wait for MII (in milliseconds) */
|
||||||
#define SMSCUSB_MII_MAX_WAIT_MS 100
|
#define SMSCUSB_MII_MAX_WAIT_MS 100
|
||||||
|
|
||||||
|
@ -166,6 +154,8 @@ struct smscusb_device {
|
||||||
struct mii_interface mii;
|
struct mii_interface mii;
|
||||||
/** MII register base */
|
/** MII register base */
|
||||||
uint16_t mii_base;
|
uint16_t mii_base;
|
||||||
|
/** PHY interrupt source register */
|
||||||
|
uint16_t phy_source;
|
||||||
/** Interrupt status */
|
/** Interrupt status */
|
||||||
uint32_t int_sts;
|
uint32_t int_sts;
|
||||||
};
|
};
|
||||||
|
@ -279,12 +269,15 @@ smscusb_init ( struct smscusb_device *smscusb, struct net_device *netdev,
|
||||||
*
|
*
|
||||||
* @v smscusb SMSC USB device
|
* @v smscusb SMSC USB device
|
||||||
* @v mii_base MII register base
|
* @v mii_base MII register base
|
||||||
|
* @v phy_source Interrupt source PHY register
|
||||||
*/
|
*/
|
||||||
static inline __attribute__ (( always_inline )) void
|
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 );
|
mii_init ( &smscusb->mii, &smscusb_mii_operations );
|
||||||
smscusb->mii_base = mii_base;
|
smscusb->mii_base = mii_base;
|
||||||
|
smscusb->phy_source = phy_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb,
|
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,
|
extern int smscusb_otp_fetch_mac ( struct smscusb_device *smscusb,
|
||||||
unsigned int otp_base );
|
unsigned int otp_base );
|
||||||
extern int smscusb_mii_check_link ( struct smscusb_device *smscusb );
|
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,
|
extern int smscusb_set_address ( struct smscusb_device *smscusb,
|
||||||
unsigned int addr_base );
|
unsigned int addr_base );
|
||||||
extern int smscusb_set_filter ( struct smscusb_device *smscusb,
|
extern int smscusb_set_filter ( struct smscusb_device *smscusb,
|
||||||
|
|
Reference in New Issue