converted atheros ethernet driver to phy layer
SVN-Revision: 9298
This commit is contained in:
parent
f0e10e1253
commit
8f7311e20b
3 changed files with 156 additions and 215 deletions
|
@ -10,6 +10,7 @@ CONFIG_ATHEROS_AR5315=y
|
||||||
# CONFIG_ATM is not set
|
# CONFIG_ATM is not set
|
||||||
CONFIG_BASE_SMALL=0
|
CONFIG_BASE_SMALL=0
|
||||||
CONFIG_BITREVERSE=y
|
CONFIG_BITREVERSE=y
|
||||||
|
# CONFIG_BROADCOM_PHY is not set
|
||||||
# CONFIG_BT is not set
|
# CONFIG_BT is not set
|
||||||
CONFIG_CMDLINE="console=ttyS0,9600 rootfstype=squashfs,jffs2 init=/etc/preinit"
|
CONFIG_CMDLINE="console=ttyS0,9600 rootfstype=squashfs,jffs2 init=/etc/preinit"
|
||||||
CONFIG_CPU_BIG_ENDIAN=y
|
CONFIG_CPU_BIG_ENDIAN=y
|
||||||
|
@ -45,16 +46,17 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||||
# CONFIG_DM9000 is not set
|
# CONFIG_DM9000 is not set
|
||||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||||
CONFIG_DMA_NONCOHERENT=y
|
CONFIG_DMA_NONCOHERENT=y
|
||||||
|
# CONFIG_FIXED_PHY is not set
|
||||||
CONFIG_FS_POSIX_ACL=y
|
CONFIG_FS_POSIX_ACL=y
|
||||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
||||||
CONFIG_HAS_DMA=y
|
CONFIG_HAS_DMA=y
|
||||||
CONFIG_HAS_IOMEM=y
|
CONFIG_HAS_IOMEM=y
|
||||||
CONFIG_HAS_IOPORT=y
|
CONFIG_HAS_IOPORT=y
|
||||||
CONFIG_HAVE_STD_PC_SERIAL_PORT=y
|
|
||||||
# CONFIG_HOSTAP is not set
|
# CONFIG_HOSTAP is not set
|
||||||
CONFIG_HW_RANDOM=y
|
CONFIG_HW_RANDOM=y
|
||||||
# CONFIG_I2C is not set
|
# CONFIG_I2C is not set
|
||||||
|
CONFIG_ICPLUS_PHY=y
|
||||||
# CONFIG_IDE is not set
|
# CONFIG_IDE is not set
|
||||||
# CONFIG_IEEE80211 is not set
|
# CONFIG_IEEE80211 is not set
|
||||||
CONFIG_INITRAMFS_SOURCE=""
|
CONFIG_INITRAMFS_SOURCE=""
|
||||||
|
@ -127,15 +129,22 @@ CONFIG_MTD_REDBOOT_PARTS_READONLY=y
|
||||||
# CONFIG_MTD_ROM is not set
|
# CONFIG_MTD_ROM is not set
|
||||||
# CONFIG_MTD_SLRAM is not set
|
# CONFIG_MTD_SLRAM is not set
|
||||||
CONFIG_MTD_SPIFLASH=y
|
CONFIG_MTD_SPIFLASH=y
|
||||||
|
CONFIG_NETDEV_1000=y
|
||||||
|
CONFIG_NET_ACT_POLICE=y
|
||||||
|
CONFIG_NET_SCH_FIFO=y
|
||||||
|
CONFIG_NF_CT_PROTO_GRE=m
|
||||||
|
CONFIG_NF_NAT_PROTO_GRE=m
|
||||||
# CONFIG_NO_IOPORT is not set
|
# CONFIG_NO_IOPORT is not set
|
||||||
# CONFIG_PAGE_SIZE_16KB is not set
|
# CONFIG_PAGE_SIZE_16KB is not set
|
||||||
CONFIG_PAGE_SIZE_4KB=y
|
CONFIG_PAGE_SIZE_4KB=y
|
||||||
# CONFIG_PAGE_SIZE_64KB is not set
|
# CONFIG_PAGE_SIZE_64KB is not set
|
||||||
# CONFIG_PAGE_SIZE_8KB is not set
|
# CONFIG_PAGE_SIZE_8KB is not set
|
||||||
|
CONFIG_PHYLIB=y
|
||||||
# CONFIG_PMC_MSP is not set
|
# CONFIG_PMC_MSP is not set
|
||||||
# CONFIG_PMC_YOSEMITE is not set
|
# CONFIG_PMC_YOSEMITE is not set
|
||||||
# CONFIG_PNX8550_JBS is not set
|
# CONFIG_PNX8550_JBS is not set
|
||||||
# CONFIG_PNX8550_STB810 is not set
|
# CONFIG_PNX8550_STB810 is not set
|
||||||
|
# CONFIG_QSEMI_PHY is not set
|
||||||
# CONFIG_RTC is not set
|
# CONFIG_RTC is not set
|
||||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||||
|
@ -155,6 +164,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1
|
||||||
# CONFIG_SIBYTE_RHONE is not set
|
# CONFIG_SIBYTE_RHONE is not set
|
||||||
# CONFIG_SIBYTE_SENTOSA is not set
|
# CONFIG_SIBYTE_SENTOSA is not set
|
||||||
# CONFIG_SIBYTE_SWARM is not set
|
# CONFIG_SIBYTE_SWARM is not set
|
||||||
|
# CONFIG_SMSC_PHY is not set
|
||||||
# CONFIG_SOFT_WATCHDOG is not set
|
# CONFIG_SOFT_WATCHDOG is not set
|
||||||
# CONFIG_SPARSEMEM_STATIC is not set
|
# CONFIG_SPARSEMEM_STATIC is not set
|
||||||
CONFIG_SYSVIPC_SYSCTL=y
|
CONFIG_SYSVIPC_SYSCTL=y
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/pkt_sched.h>
|
#include <linux/pkt_sched.h>
|
||||||
#include <linux/compile.h>
|
#include <linux/compile.h>
|
||||||
#include <linux/mii.h>
|
#include <linux/mii.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -144,16 +145,20 @@ MODULE_DESCRIPTION("AR2313 Ethernet driver");
|
||||||
#define virt_to_phys(x) ((u32)(x) & 0x1fffffff)
|
#define virt_to_phys(x) ((u32)(x) & 0x1fffffff)
|
||||||
|
|
||||||
// prototypes
|
// prototypes
|
||||||
static short armiiread(struct net_device *dev, short phy, short reg);
|
|
||||||
static void armiiwrite(struct net_device *dev, short phy, short reg,
|
|
||||||
short data);
|
|
||||||
#ifdef TX_TIMEOUT
|
#ifdef TX_TIMEOUT
|
||||||
static void ar2313_tx_timeout(struct net_device *dev);
|
static void ar2313_tx_timeout(struct net_device *dev);
|
||||||
#endif
|
#endif
|
||||||
static void ar2313_halt(struct net_device *dev);
|
static void ar2313_halt(struct net_device *dev);
|
||||||
static void rx_tasklet_func(unsigned long data);
|
static void rx_tasklet_func(unsigned long data);
|
||||||
|
static void rx_tasklet_cleanup(struct net_device *dev);
|
||||||
static void ar2313_multicast_list(struct net_device *dev);
|
static void ar2313_multicast_list(struct net_device *dev);
|
||||||
|
|
||||||
|
static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum);
|
||||||
|
static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value);
|
||||||
|
static int mdiobus_reset(struct mii_bus *bus);
|
||||||
|
static int mdiobus_probe (struct net_device *dev);
|
||||||
|
static void ar2313_adjust_link(struct net_device *dev);
|
||||||
|
|
||||||
#ifndef ERR
|
#ifndef ERR
|
||||||
#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
|
#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
|
||||||
#endif
|
#endif
|
||||||
|
@ -277,9 +282,28 @@ int __init ar2313_probe(struct platform_device *pdev)
|
||||||
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
|
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
|
||||||
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq);
|
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq);
|
||||||
|
|
||||||
/* start link poll timer */
|
sp->mii_bus.priv = dev;
|
||||||
ar2313_setup_timer(dev);
|
sp->mii_bus.read = mdiobus_read;
|
||||||
|
sp->mii_bus.write = mdiobus_write;
|
||||||
|
sp->mii_bus.reset = mdiobus_reset;
|
||||||
|
sp->mii_bus.name = "ar2313_eth_mii";
|
||||||
|
sp->mii_bus.id = 0;
|
||||||
|
sp->mii_bus.irq = kmalloc(sizeof(int), GFP_KERNEL);
|
||||||
|
*sp->mii_bus.irq = PHY_POLL;
|
||||||
|
|
||||||
|
mdiobus_register(&sp->mii_bus);
|
||||||
|
|
||||||
|
if (mdiobus_probe(dev) != 0) {
|
||||||
|
printk(KERN_ERR "ar2313: mdiobus_probe failed");
|
||||||
|
rx_tasklet_cleanup(dev);
|
||||||
|
ar2313_init_cleanup(dev);
|
||||||
|
unregister_netdev(dev);
|
||||||
|
kfree(dev);
|
||||||
|
} else {
|
||||||
|
/* start link poll timer */
|
||||||
|
ar2313_setup_timer(dev);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +615,7 @@ static void ar2313_check_link(struct net_device *dev)
|
||||||
struct ar2313_private *sp = dev->priv;
|
struct ar2313_private *sp = dev->priv;
|
||||||
u16 phyData;
|
u16 phyData;
|
||||||
|
|
||||||
phyData = armiiread(dev, sp->phy, MII_BMSR);
|
phyData = mdiobus_read(&sp->mii_bus, sp->phy, MII_BMSR);
|
||||||
if (sp->phyData != phyData) {
|
if (sp->phyData != phyData) {
|
||||||
if (phyData & BMSR_LSTATUS) {
|
if (phyData & BMSR_LSTATUS) {
|
||||||
/* link is present, ready link partner ability to deterine
|
/* link is present, ready link partner ability to deterine
|
||||||
|
@ -600,10 +624,10 @@ static void ar2313_check_link(struct net_device *dev)
|
||||||
u16 reg;
|
u16 reg;
|
||||||
|
|
||||||
sp->link = 1;
|
sp->link = 1;
|
||||||
reg = armiiread(dev, sp->phy, MII_BMCR);
|
reg = mdiobus_read(&sp->mii_bus, sp->phy, MII_BMCR);
|
||||||
if (reg & BMCR_ANENABLE) {
|
if (reg & BMCR_ANENABLE) {
|
||||||
/* auto neg enabled */
|
/* auto neg enabled */
|
||||||
reg = armiiread(dev, sp->phy, MII_LPA);
|
reg = mdiobus_read(&sp->mii_bus, sp->phy, MII_LPA);
|
||||||
duplex = (reg & (LPA_100FULL | LPA_10FULL)) ? 1 : 0;
|
duplex = (reg & (LPA_100FULL | LPA_10FULL)) ? 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
/* no auto neg, just read duplex config */
|
/* no auto neg, just read duplex config */
|
||||||
|
@ -1217,194 +1241,19 @@ static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netdev_get_ecmd(struct net_device *dev,
|
|
||||||
struct ethtool_cmd *ecmd)
|
|
||||||
{
|
|
||||||
struct ar2313_private *np = dev->priv;
|
|
||||||
u32 tmp;
|
|
||||||
|
|
||||||
ecmd->supported =
|
|
||||||
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
|
|
||||||
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
|
|
||||||
SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
|
|
||||||
|
|
||||||
ecmd->port = PORT_TP;
|
|
||||||
/* only supports internal transceiver */
|
|
||||||
ecmd->transceiver = XCVR_INTERNAL;
|
|
||||||
/* not sure what this is for */
|
|
||||||
ecmd->phy_address = 1;
|
|
||||||
|
|
||||||
ecmd->advertising = ADVERTISED_MII;
|
|
||||||
tmp = armiiread(dev, np->phy, MII_ADVERTISE);
|
|
||||||
if (tmp & ADVERTISE_10HALF)
|
|
||||||
ecmd->advertising |= ADVERTISED_10baseT_Half;
|
|
||||||
if (tmp & ADVERTISE_10FULL)
|
|
||||||
ecmd->advertising |= ADVERTISED_10baseT_Full;
|
|
||||||
if (tmp & ADVERTISE_100HALF)
|
|
||||||
ecmd->advertising |= ADVERTISED_100baseT_Half;
|
|
||||||
if (tmp & ADVERTISE_100FULL)
|
|
||||||
ecmd->advertising |= ADVERTISED_100baseT_Full;
|
|
||||||
|
|
||||||
tmp = armiiread(dev, np->phy, MII_BMCR);
|
|
||||||
if (tmp & BMCR_ANENABLE) {
|
|
||||||
ecmd->advertising |= ADVERTISED_Autoneg;
|
|
||||||
ecmd->autoneg = AUTONEG_ENABLE;
|
|
||||||
} else {
|
|
||||||
ecmd->autoneg = AUTONEG_DISABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ecmd->autoneg == AUTONEG_ENABLE) {
|
|
||||||
tmp = armiiread(dev, np->phy, MII_LPA);
|
|
||||||
if (tmp & (LPA_100FULL | LPA_10FULL)) {
|
|
||||||
ecmd->duplex = DUPLEX_FULL;
|
|
||||||
} else {
|
|
||||||
ecmd->duplex = DUPLEX_HALF;
|
|
||||||
}
|
|
||||||
if (tmp & (LPA_100FULL | LPA_100HALF)) {
|
|
||||||
ecmd->speed = SPEED_100;
|
|
||||||
} else {
|
|
||||||
ecmd->speed = SPEED_10;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tmp & BMCR_FULLDPLX) {
|
|
||||||
ecmd->duplex = DUPLEX_FULL;
|
|
||||||
} else {
|
|
||||||
ecmd->duplex = DUPLEX_HALF;
|
|
||||||
}
|
|
||||||
if (tmp & BMCR_SPEED100) {
|
|
||||||
ecmd->speed = SPEED_100;
|
|
||||||
} else {
|
|
||||||
ecmd->speed = SPEED_10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ignore maxtxpkt, maxrxpkt for now */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int netdev_set_ecmd(struct net_device *dev,
|
|
||||||
struct ethtool_cmd *ecmd)
|
|
||||||
{
|
|
||||||
struct ar2313_private *np = dev->priv;
|
|
||||||
u32 tmp;
|
|
||||||
|
|
||||||
if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
|
|
||||||
return -EINVAL;
|
|
||||||
if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
|
|
||||||
return -EINVAL;
|
|
||||||
if (ecmd->port != PORT_TP)
|
|
||||||
return -EINVAL;
|
|
||||||
if (ecmd->transceiver != XCVR_INTERNAL)
|
|
||||||
return -EINVAL;
|
|
||||||
if (ecmd->autoneg != AUTONEG_DISABLE
|
|
||||||
&& ecmd->autoneg != AUTONEG_ENABLE)
|
|
||||||
return -EINVAL;
|
|
||||||
/* ignore phy_address, maxtxpkt, maxrxpkt for now */
|
|
||||||
|
|
||||||
/* WHEW! now lets bang some bits */
|
|
||||||
|
|
||||||
tmp = armiiread(dev, np->phy, MII_BMCR);
|
|
||||||
if (ecmd->autoneg == AUTONEG_ENABLE) {
|
|
||||||
/* turn on autonegotiation */
|
|
||||||
tmp |= BMCR_ANENABLE;
|
|
||||||
printk("%s: Enabling auto-neg\n", dev->name);
|
|
||||||
} else {
|
|
||||||
/* turn off auto negotiation, set speed and duplexity */
|
|
||||||
tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
|
|
||||||
if (ecmd->speed == SPEED_100)
|
|
||||||
tmp |= BMCR_SPEED100;
|
|
||||||
if (ecmd->duplex == DUPLEX_FULL)
|
|
||||||
tmp |= BMCR_FULLDPLX;
|
|
||||||
printk("%s: Hard coding %d/%s\n", dev->name,
|
|
||||||
(ecmd->speed == SPEED_100) ? 100 : 10,
|
|
||||||
(ecmd->duplex == DUPLEX_FULL) ? "full" : "half");
|
|
||||||
}
|
|
||||||
armiiwrite(dev, np->phy, MII_BMCR, tmp);
|
|
||||||
np->phyData = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
|
|
||||||
{
|
|
||||||
struct ar2313_private *np = dev->priv;
|
|
||||||
u32 cmd;
|
|
||||||
|
|
||||||
if (get_user(cmd, (u32 *) useraddr))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
/* get settings */
|
|
||||||
case ETHTOOL_GSET:{
|
|
||||||
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
|
|
||||||
spin_lock_irq(&np->lock);
|
|
||||||
netdev_get_ecmd(dev, &ecmd);
|
|
||||||
spin_unlock_irq(&np->lock);
|
|
||||||
if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* set settings */
|
|
||||||
case ETHTOOL_SSET:{
|
|
||||||
struct ethtool_cmd ecmd;
|
|
||||||
int r;
|
|
||||||
if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
|
|
||||||
return -EFAULT;
|
|
||||||
spin_lock_irq(&np->lock);
|
|
||||||
r = netdev_set_ecmd(dev, &ecmd);
|
|
||||||
spin_unlock_irq(&np->lock);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
/* restart autonegotiation */
|
|
||||||
case ETHTOOL_NWAY_RST:{
|
|
||||||
int tmp;
|
|
||||||
int r = -EINVAL;
|
|
||||||
/* if autoneg is off, it's an error */
|
|
||||||
tmp = armiiread(dev, np->phy, MII_BMCR);
|
|
||||||
if (tmp & BMCR_ANENABLE) {
|
|
||||||
tmp |= (BMCR_ANRESTART);
|
|
||||||
armiiwrite(dev, np->phy, MII_BMCR, tmp);
|
|
||||||
r = 0;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
/* get link status */
|
|
||||||
case ETHTOOL_GLINK:{
|
|
||||||
struct ethtool_value edata = { ETHTOOL_GLINK };
|
|
||||||
edata.data =
|
|
||||||
(armiiread(dev, np->phy, MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
|
|
||||||
if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
{
|
{
|
||||||
struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_data;
|
struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_data;
|
||||||
|
struct ar2313_private *sp = dev->priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
||||||
case SIOCETHTOOL:
|
case SIOCETHTOOL:
|
||||||
return netdev_ethtool_ioctl(dev, (void *) ifr->ifr_data);
|
spin_lock_irq(&sp->lock);
|
||||||
|
ret = phy_ethtool_ioctl(sp->phy_dev, (void *) ifr->ifr_data);
|
||||||
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
|
spin_unlock_irq(&sp->lock);
|
||||||
data->phy_id = 1;
|
return ret;
|
||||||
/* Fall Through */
|
|
||||||
|
|
||||||
case SIOCGMIIREG: /* Read MII PHY register. */
|
|
||||||
data->val_out = armiiread(dev, data->phy_id & 0x1f,
|
|
||||||
data->reg_num & 0x1f);
|
|
||||||
return 0;
|
|
||||||
case SIOCSMIIREG: /* Write MII PHY register. */
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
|
||||||
return -EPERM;
|
|
||||||
armiiwrite(dev, data->phy_id & 0x1f,
|
|
||||||
data->reg_num & 0x1f, data->val_in);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SIOCSIFHWADDR:
|
case SIOCSIFHWADDR:
|
||||||
if (copy_from_user
|
if (copy_from_user
|
||||||
|
@ -1417,7 +1266,12 @@ static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr)))
|
(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case SIOCGMIIPHY:
|
||||||
|
case SIOCGMIIREG:
|
||||||
|
case SIOCSMIIREG:
|
||||||
|
return phy_mii_ioctl(sp->phy_dev, data, cmd);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1432,26 +1286,101 @@ static struct net_device_stats *ar2313_get_stats(struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ar2313_adjust_link(struct net_device *dev)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR " ar2313_adjust_link implementation missing\n");
|
||||||
|
}
|
||||||
|
|
||||||
#define MII_ADDR(phy, reg) \
|
#define MII_ADDR(phy, reg) \
|
||||||
((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT))
|
((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT))
|
||||||
|
|
||||||
static short armiiread(struct net_device *dev, short phy, short reg)
|
static int
|
||||||
|
mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
|
||||||
{
|
{
|
||||||
|
struct net_device *const dev = bus->priv;
|
||||||
struct ar2313_private *sp = (struct ar2313_private *) dev->priv;
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv;
|
||||||
volatile ETHERNET_STRUCT *ethernet = sp->phy_regs;
|
volatile ETHERNET_STRUCT *ethernet = sp->phy_regs;
|
||||||
|
|
||||||
ethernet->mii_addr = MII_ADDR(phy, reg);
|
ethernet->mii_addr = MII_ADDR(phy_addr, regnum);
|
||||||
while (ethernet->mii_addr & MII_ADDR_BUSY);
|
while (ethernet->mii_addr & MII_ADDR_BUSY);
|
||||||
return (ethernet->mii_data >> MII_DATA_SHIFT);
|
return (ethernet->mii_data >> MII_DATA_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
armiiwrite(struct net_device *dev, short phy, short reg, short data)
|
mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
|
||||||
|
u16 value)
|
||||||
{
|
{
|
||||||
|
struct net_device *const dev = bus->priv;
|
||||||
struct ar2313_private *sp = (struct ar2313_private *) dev->priv;
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv;
|
||||||
volatile ETHERNET_STRUCT *ethernet = sp->phy_regs;
|
volatile ETHERNET_STRUCT *ethernet = sp->phy_regs;
|
||||||
|
|
||||||
while (ethernet->mii_addr & MII_ADDR_BUSY);
|
while (ethernet->mii_addr & MII_ADDR_BUSY);
|
||||||
ethernet->mii_data = data << MII_DATA_SHIFT;
|
ethernet->mii_data = value << MII_DATA_SHIFT;
|
||||||
ethernet->mii_addr = MII_ADDR(phy, reg) | MII_ADDR_WRITE;
|
ethernet->mii_addr = MII_ADDR(phy_addr, regnum) | MII_ADDR_WRITE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mdiobus_reset(struct mii_bus *bus)
|
||||||
|
{
|
||||||
|
struct net_device *const dev = bus->priv;
|
||||||
|
|
||||||
|
ar2313_reset_reg(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mdiobus_probe (struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct ar2313_private *const sp = (struct ar2313_private *) dev->priv;
|
||||||
|
struct phy_device *phydev = NULL;
|
||||||
|
int phy_addr;
|
||||||
|
|
||||||
|
/* find the first (lowest address) PHY on the current MAC's MII bus */
|
||||||
|
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
|
||||||
|
if (sp->mii_bus.phy_map[phy_addr]) {
|
||||||
|
phydev = sp->mii_bus.phy_map[phy_addr];
|
||||||
|
break; /* break out with first one found */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!phydev) {
|
||||||
|
printk (KERN_ERR "ar2313:%s: no PHY found\n", dev->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now we are supposed to have a proper phydev, to attach to... */
|
||||||
|
BUG_ON(!phydev);
|
||||||
|
BUG_ON(phydev->attached_dev);
|
||||||
|
|
||||||
|
phydev = phy_connect(dev, phydev->dev.bus_id, &ar2313_adjust_link, 0,
|
||||||
|
PHY_INTERFACE_MODE_MII);
|
||||||
|
|
||||||
|
if (IS_ERR(phydev)) {
|
||||||
|
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
|
||||||
|
return PTR_ERR(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mask with MAC supported features */
|
||||||
|
phydev->supported &= (SUPPORTED_10baseT_Half
|
||||||
|
| SUPPORTED_10baseT_Full
|
||||||
|
| SUPPORTED_100baseT_Half
|
||||||
|
| SUPPORTED_100baseT_Full
|
||||||
|
| SUPPORTED_Autoneg
|
||||||
|
/* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
|
||||||
|
| SUPPORTED_MII
|
||||||
|
| SUPPORTED_TP);
|
||||||
|
|
||||||
|
phydev->advertising = phydev->supported;
|
||||||
|
|
||||||
|
//sp->old_link = 0;
|
||||||
|
//sp->old_speed = 0;
|
||||||
|
//sp->old_duplex = -1;
|
||||||
|
sp->phy_dev = phydev;
|
||||||
|
|
||||||
|
printk(KERN_INFO "%s: attached PHY driver [%s] "
|
||||||
|
"(mii_bus:phy_addr=%s)\n",
|
||||||
|
dev->name, phydev->drv->name, phydev->dev.bus_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
diff -urN linux.old/drivers/net/Kconfig linux.eth/drivers/net/Kconfig
|
Index: linux-2.6.23/drivers/net/Kconfig
|
||||||
--- linux.old/drivers/net/Kconfig 2006-12-14 23:53:29.000000000 +0100
|
===================================================================
|
||||||
+++ linux.eth/drivers/net/Kconfig 2006-12-16 04:30:11.000000000 +0100
|
--- linux-2.6.23.orig/drivers/net/Kconfig 2007-10-14 00:55:22.000000000 +0200
|
||||||
@@ -324,6 +324,12 @@
|
+++ linux-2.6.23/drivers/net/Kconfig 2007-10-14 00:56:32.000000000 +0200
|
||||||
|
@@ -348,6 +348,12 @@
|
||||||
source "drivers/net/arm/Kconfig"
|
AX88796 driver, using platform bus to provide
|
||||||
|
chip detection and resources
|
||||||
|
|
||||||
+config AR2313
|
+config AR2313
|
||||||
+ tristate "AR2313 Ethernet support"
|
+ tristate "AR2313 Ethernet support"
|
||||||
|
@ -13,15 +14,16 @@ diff -urN linux.old/drivers/net/Kconfig linux.eth/drivers/net/Kconfig
|
||||||
+
|
+
|
||||||
config MACE
|
config MACE
|
||||||
tristate "MACE (Power Mac ethernet) support"
|
tristate "MACE (Power Mac ethernet) support"
|
||||||
depends on NET_ETHERNET && PPC_PMAC && PPC32
|
depends on PPC_PMAC && PPC32
|
||||||
diff -urN linux.old/drivers/net/Makefile linux.eth/drivers/net/Makefile
|
Index: linux-2.6.23/drivers/net/Makefile
|
||||||
--- linux.old/drivers/net/Makefile 2006-12-14 23:53:29.000000000 +0100
|
===================================================================
|
||||||
+++ linux.eth/drivers/net/Makefile 2006-12-16 04:30:11.000000000 +0100
|
--- linux-2.6.23.orig/drivers/net/Makefile 2007-10-14 00:55:22.000000000 +0200
|
||||||
@@ -11,6 +11,7 @@
|
+++ linux-2.6.23/drivers/net/Makefile 2007-10-14 00:56:55.000000000 +0200
|
||||||
obj-$(CONFIG_BONDING) += bonding/
|
@@ -182,6 +182,7 @@
|
||||||
obj-$(CONFIG_ATL1) += atl1/
|
obj-$(CONFIG_LGUEST_NET) += lguest_net.o
|
||||||
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
|
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
|
||||||
|
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
|
||||||
+obj-$(CONFIG_AR2313) += ar2313/
|
+obj-$(CONFIG_AR2313) += ar2313/
|
||||||
|
obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
|
||||||
gianfar_driver-objs := gianfar.o \
|
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
|
||||||
gianfar_ethtool.o \
|
obj-$(CONFIG_DECLANCE) += declance.o
|
||||||
|
|
Loading…
Reference in a new issue