90b24cfb42
I no longer have a mailbox at smsc.com, and I've had two reports that that email address now bounces from people trying to contact me. This patch updates all references to that invalid address to one that I can be contacted on more permanently. This patch also updates the maintainer status to reflect the fact I'm no longer directly paid to maintain these drivers. Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
248 lines
5.8 KiB
C
248 lines
5.8 KiB
C
/*
|
|
* drivers/net/phy/smsc.c
|
|
*
|
|
* Driver for SMSC PHYs
|
|
*
|
|
* Author: Herbert Valerio Riedel
|
|
*
|
|
* Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
|
|
*
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mii.h>
|
|
#include <linux/ethtool.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/smscphy.h>
|
|
|
|
static int smsc_phy_config_intr(struct phy_device *phydev)
|
|
{
|
|
int rc = phy_write (phydev, MII_LAN83C185_IM,
|
|
((PHY_INTERRUPT_ENABLED == phydev->interrupts)
|
|
? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
|
|
: 0));
|
|
|
|
return rc < 0 ? rc : 0;
|
|
}
|
|
|
|
static int smsc_phy_ack_interrupt(struct phy_device *phydev)
|
|
{
|
|
int rc = phy_read (phydev, MII_LAN83C185_ISF);
|
|
|
|
return rc < 0 ? rc : 0;
|
|
}
|
|
|
|
static int smsc_phy_config_init(struct phy_device *phydev)
|
|
{
|
|
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
/* Enable energy detect mode for this SMSC Transceivers */
|
|
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
|
|
rc | MII_LAN83C185_EDPWRDOWN);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
return smsc_phy_ack_interrupt (phydev);
|
|
}
|
|
|
|
static int lan911x_config_init(struct phy_device *phydev)
|
|
{
|
|
return smsc_phy_ack_interrupt(phydev);
|
|
}
|
|
|
|
static struct phy_driver lan83c185_driver = {
|
|
.phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
|
|
.phy_id_mask = 0xfffffff0,
|
|
.name = "SMSC LAN83C185",
|
|
|
|
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
|
|
| SUPPORTED_Asym_Pause),
|
|
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
|
|
|
|
/* basic functions */
|
|
.config_aneg = genphy_config_aneg,
|
|
.read_status = genphy_read_status,
|
|
.config_init = smsc_phy_config_init,
|
|
|
|
/* IRQ related */
|
|
.ack_interrupt = smsc_phy_ack_interrupt,
|
|
.config_intr = smsc_phy_config_intr,
|
|
|
|
.suspend = genphy_suspend,
|
|
.resume = genphy_resume,
|
|
|
|
.driver = { .owner = THIS_MODULE, }
|
|
};
|
|
|
|
static struct phy_driver lan8187_driver = {
|
|
.phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
|
|
.phy_id_mask = 0xfffffff0,
|
|
.name = "SMSC LAN8187",
|
|
|
|
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
|
|
| SUPPORTED_Asym_Pause),
|
|
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
|
|
|
|
/* basic functions */
|
|
.config_aneg = genphy_config_aneg,
|
|
.read_status = genphy_read_status,
|
|
.config_init = smsc_phy_config_init,
|
|
|
|
/* IRQ related */
|
|
.ack_interrupt = smsc_phy_ack_interrupt,
|
|
.config_intr = smsc_phy_config_intr,
|
|
|
|
.suspend = genphy_suspend,
|
|
.resume = genphy_resume,
|
|
|
|
.driver = { .owner = THIS_MODULE, }
|
|
};
|
|
|
|
static struct phy_driver lan8700_driver = {
|
|
.phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
|
|
.phy_id_mask = 0xfffffff0,
|
|
.name = "SMSC LAN8700",
|
|
|
|
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
|
|
| SUPPORTED_Asym_Pause),
|
|
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
|
|
|
|
/* basic functions */
|
|
.config_aneg = genphy_config_aneg,
|
|
.read_status = genphy_read_status,
|
|
.config_init = smsc_phy_config_init,
|
|
|
|
/* IRQ related */
|
|
.ack_interrupt = smsc_phy_ack_interrupt,
|
|
.config_intr = smsc_phy_config_intr,
|
|
|
|
.suspend = genphy_suspend,
|
|
.resume = genphy_resume,
|
|
|
|
.driver = { .owner = THIS_MODULE, }
|
|
};
|
|
|
|
static struct phy_driver lan911x_int_driver = {
|
|
.phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
|
|
.phy_id_mask = 0xfffffff0,
|
|
.name = "SMSC LAN911x Internal PHY",
|
|
|
|
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
|
|
| SUPPORTED_Asym_Pause),
|
|
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
|
|
|
|
/* basic functions */
|
|
.config_aneg = genphy_config_aneg,
|
|
.read_status = genphy_read_status,
|
|
.config_init = lan911x_config_init,
|
|
|
|
/* IRQ related */
|
|
.ack_interrupt = smsc_phy_ack_interrupt,
|
|
.config_intr = smsc_phy_config_intr,
|
|
|
|
.suspend = genphy_suspend,
|
|
.resume = genphy_resume,
|
|
|
|
.driver = { .owner = THIS_MODULE, }
|
|
};
|
|
|
|
static struct phy_driver lan8710_driver = {
|
|
.phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
|
|
.phy_id_mask = 0xfffffff0,
|
|
.name = "SMSC LAN8710/LAN8720",
|
|
|
|
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
|
|
| SUPPORTED_Asym_Pause),
|
|
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
|
|
|
|
/* basic functions */
|
|
.config_aneg = genphy_config_aneg,
|
|
.read_status = genphy_read_status,
|
|
.config_init = smsc_phy_config_init,
|
|
|
|
/* IRQ related */
|
|
.ack_interrupt = smsc_phy_ack_interrupt,
|
|
.config_intr = smsc_phy_config_intr,
|
|
|
|
.suspend = genphy_suspend,
|
|
.resume = genphy_resume,
|
|
|
|
.driver = { .owner = THIS_MODULE, }
|
|
};
|
|
|
|
static int __init smsc_init(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = phy_driver_register (&lan83c185_driver);
|
|
if (ret)
|
|
goto err1;
|
|
|
|
ret = phy_driver_register (&lan8187_driver);
|
|
if (ret)
|
|
goto err2;
|
|
|
|
ret = phy_driver_register (&lan8700_driver);
|
|
if (ret)
|
|
goto err3;
|
|
|
|
ret = phy_driver_register (&lan911x_int_driver);
|
|
if (ret)
|
|
goto err4;
|
|
|
|
ret = phy_driver_register (&lan8710_driver);
|
|
if (ret)
|
|
goto err5;
|
|
|
|
return 0;
|
|
|
|
err5:
|
|
phy_driver_unregister (&lan911x_int_driver);
|
|
err4:
|
|
phy_driver_unregister (&lan8700_driver);
|
|
err3:
|
|
phy_driver_unregister (&lan8187_driver);
|
|
err2:
|
|
phy_driver_unregister (&lan83c185_driver);
|
|
err1:
|
|
return ret;
|
|
}
|
|
|
|
static void __exit smsc_exit(void)
|
|
{
|
|
phy_driver_unregister (&lan8710_driver);
|
|
phy_driver_unregister (&lan911x_int_driver);
|
|
phy_driver_unregister (&lan8700_driver);
|
|
phy_driver_unregister (&lan8187_driver);
|
|
phy_driver_unregister (&lan83c185_driver);
|
|
}
|
|
|
|
MODULE_DESCRIPTION("SMSC PHY driver");
|
|
MODULE_AUTHOR("Herbert Valerio Riedel");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
module_init(smsc_init);
|
|
module_exit(smsc_exit);
|
|
|
|
static struct mdio_device_id __maybe_unused smsc_tbl[] = {
|
|
{ 0x0007c0a0, 0xfffffff0 },
|
|
{ 0x0007c0b0, 0xfffffff0 },
|
|
{ 0x0007c0c0, 0xfffffff0 },
|
|
{ 0x0007c0d0, 0xfffffff0 },
|
|
{ 0x0007c0f0, 0xfffffff0 },
|
|
{ }
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(mdio, smsc_tbl);
|