summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2006-06-01 09:41:04 +0200
committerJeff Garzik <jeff@garzik.org>2006-06-11 23:19:00 -0400
commit0638dec01e89059c853515ab71c55fd13ba5a8ea (patch)
tree7743a5714b03ef408b3147475cfe61127d580ed3 /drivers/net
parent96e672c79fb114ec38a868dc864e743205c24332 (diff)
[PATCH] net: au1000_eth: PHY framework conversion
convert au1000_eth driver to use PHY framework and garbage collected functions and identifiers that became unused/obsolete in the process Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/au1000_eth.c1602
-rw-r--r--drivers/net/au1000_eth.h134
3 files changed, 378 insertions, 1359 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2f0b2549e9ec..20bdb9732a09 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -447,6 +447,7 @@ config MIPS_GT96100ETH
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && SOC_AU1X00
+ select PHYLIB
select CRC32
help
If you have an Alchemy Semi AU1X00 based system
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index e1fe960d71b3..038d5fcb15e6 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -9,6 +9,9 @@
* Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de
* or riemer@riemer-nt.de: fixed the link beat detection with
* ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ * converted to use linux-2.6.x's PHY framework
+ *
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
@@ -53,6 +56,7 @@
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/crc32.h>
+#include <linux/phy.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -88,17 +92,15 @@ static int au1000_tx(struct sk_buff *, struct net_device *);
static int au1000_rx(struct net_device *);
static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
static void au1000_tx_timeout(struct net_device *);
-static int au1000_set_config(struct net_device *dev, struct ifmap *map);
static void set_rx_mode(struct net_device *);
static struct net_device_stats *au1000_get_stats(struct net_device *);
-static void au1000_timer(unsigned long);
static int au1000_ioctl(struct net_device *, struct ifreq *, int);
static int mdio_read(struct net_device *, int, int);
static void mdio_write(struct net_device *, int, int, u16);
-static void dump_mii(struct net_device *dev, int phy_id);
+static void au1000_adjust_link(struct net_device *);
+static void enable_mac(struct net_device *, int);
// externs
-extern void ack_rise_edge_irq(unsigned int);
extern int get_ethernet_addr(char *ethernet_addr);
extern void str2eaddr(unsigned char *ea, unsigned char *str);
extern char * __init prom_getcmdline(void);
@@ -126,705 +128,83 @@ static unsigned char au1000_mac_addr[6] __devinitdata = {
0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
};
-#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
-#define RUN_AT(x) (jiffies + (x))
-
-// For reading/writing 32-bit words from/to DMA memory
-#define cpu_to_dma32 cpu_to_be32
-#define dma32_to_cpu be32_to_cpu
-
struct au1000_private *au_macs[NUM_ETH_INTERFACES];
-/* FIXME
- * All of the PHY code really should be detached from the MAC
- * code.
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
*/
-/* Default advertise */
-#define GENMII_DEFAULT_ADVERTISE \
- ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
- ADVERTISED_Autoneg
-
-#define GENMII_DEFAULT_FEATURES \
- SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg
-
-int bcm_5201_init(struct net_device *dev, int phy_addr)
-{
- s16 data;
-
- /* Stop auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
- /* Set advertisement to 10/100 and Half/Full duplex
- * (full capabilities) */
- data = mdio_read(dev, phy_addr, MII_ANADV);
- data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
- mdio_write(dev, phy_addr, MII_ANADV, data);
-
- /* Restart auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
- mdio_write(dev, phy_addr, MII_CONTROL, data);
-
- if (au1000_debug > 4)
- dump_mii(dev, phy_addr);
- return 0;
-}
-
-int bcm_5201_reset(struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int
-bcm_5201_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- if (!dev) {
- printk(KERN_ERR "bcm_5201_status error: NULL dev\n");
- return -1;
- }
- aup = (struct au1000_private *) dev->priv;
-
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
- if (mii_data & MII_AUX_100) {
- if (mii_data & MII_AUX_FDX) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
-
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-int lsi_80227_init(struct net_device *dev, int phy_addr)
-{
- if (au1000_debug > 4)
- printk("lsi_80227_init\n");
-
- /* restart auto-negotiation */
- mdio_write(dev, phy_addr, MII_CONTROL,
- MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX);
- mdelay(1);
-
- /* set up LEDs to correct display */
-#ifdef CONFIG_MIPS_MTX1
- mdio_write(dev, phy_addr, 17, 0xff80);
-#else
- mdio_write(dev, phy_addr, 17, 0xffc0);
-#endif
-
- if (au1000_debug > 4)
- dump_mii(dev, phy_addr);
- return 0;
-}
-
-int lsi_80227_reset(struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
- if (au1000_debug > 4) {
- printk("lsi_80227_reset\n");
- dump_mii(dev, phy_addr);
- }
-
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int
-lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- if (!dev) {
- printk(KERN_ERR "lsi_80227_status error: NULL dev\n");
- return -1;
- }
- aup = (struct au1000_private *) dev->priv;
-
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT);
- if (mii_data & MII_LSI_PHY_STAT_SPD) {
- if (mii_data & MII_LSI_PHY_STAT_FDX) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
-
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-int am79c901_init(struct net_device *dev, int phy_addr)
-{
- printk("am79c901_init\n");
- return 0;
-}
-
-int am79c901_reset(struct net_device *dev, int phy_addr)
-{
- printk("am79c901_reset\n");
- return 0;
-}
-
-int
-am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- return 0;
-}
-
-int am79c874_init(struct net_device *dev, int phy_addr)
-{
- s16 data;
-
- /* 79c874 has quit resembled bit assignments to BCM5201 */
- if (au1000_debug > 4)
- printk("am79c847_init\n");
-
- /* Stop auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
- /* Set advertisement to 10/100 and Half/Full duplex
- * (full capabilities) */
- data = mdio_read(dev, phy_addr, MII_ANADV);
- data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
- mdio_write(dev, phy_addr, MII_ANADV, data);
-
- /* Restart auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
- mdio_write(dev, phy_addr, MII_CONTROL, data);
-
- if (au1000_debug > 4) dump_mii(dev, phy_addr);
- return 0;
-}
-
-int am79c874_reset(struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
- if (au1000_debug > 4)
- printk("am79c874_reset\n");
-
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int
-am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- // printk("am79c874_status\n");
- if (!dev) {
- printk(KERN_ERR "am79c874_status error: NULL dev\n");
- return -1;
- }
-
- aup = (struct au1000_private *) dev->priv;
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+/* autodetection defaults */
+#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR
+#define AU1XXX_PHY1_SEARCH_ON_MAC0
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT);
- if (mii_data & MII_AMD_PHY_STAT_SPD) {
- if (mii_data & MII_AMD_PHY_STAT_FDX) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
-
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-int lxt971a_init(struct net_device *dev, int phy_addr)
-{
- if (au1000_debug > 4)
- printk("lxt971a_init\n");
-
- /* restart auto-negotiation */
- mdio_write(dev, phy_addr, MII_CONTROL,
- MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX);
-
- /* set up LEDs to correct display */
- mdio_write(dev, phy_addr, 20, 0x0422);
-
- if (au1000_debug > 4)
- dump_mii(dev, phy_addr);
- return 0;
-}
-
-int lxt971a_reset(struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
- if (au1000_debug > 4) {
- printk("lxt971a_reset\n");
- dump_mii(dev, phy_addr);
- }
-
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int
-lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- if (!dev) {
- printk(KERN_ERR "lxt971a_status error: NULL dev\n");
- return -1;
- }
- aup = (struct au1000_private *) dev->priv;
-
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT);
- if (mii_data & MII_INTEL_PHY_STAT_SPD) {
- if (mii_data & MII_INTEL_PHY_STAT_FDX) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
-
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-int ks8995m_init(struct net_device *dev, int phy_addr)
-{
- s16 data;
-
-// printk("ks8995m_init\n");
- /* Stop auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
- /* Set advertisement to 10/100 and Half/Full duplex
- * (full capabilities) */
- data = mdio_read(dev, phy_addr, MII_ANADV);
- data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
- mdio_write(dev, phy_addr, MII_ANADV, data);
-
- /* Restart auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
- mdio_write(dev, phy_addr, MII_CONTROL, data);
-
- if (au1000_debug > 4) dump_mii(dev, phy_addr);
-
- return 0;
-}
-
-int ks8995m_reset(struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
-// printk("ks8995m_reset\n");
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- if (!dev) {
- printk(KERN_ERR "ks8995m_status error: NULL dev\n");
- return -1;
- }
- aup = (struct au1000_private *) dev->priv;
-
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
- if (mii_data & MII_AUX_100) {
- if (mii_data & MII_AUX_FDX) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
-
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-int
-smsc_83C185_init (struct net_device *dev, int phy_addr)
-{
- s16 data;
-
- if (au1000_debug > 4)
- printk("smsc_83C185_init\n");
-
- /* Stop auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
- /* Set advertisement to 10/100 and Half/Full duplex
- * (full capabilities) */
- data = mdio_read(dev, phy_addr, MII_ANADV);
- data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
- mdio_write(dev, phy_addr, MII_ANADV, data);
-
- /* Restart auto-negotiation */
- data = mdio_read(dev, phy_addr, MII_CONTROL);
- data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
- mdio_write(dev, phy_addr, MII_CONTROL, data);
-
- if (au1000_debug > 4) dump_mii(dev, phy_addr);
- return 0;
-}
-
-int
-smsc_83C185_reset (struct net_device *dev, int phy_addr)
-{
- s16 mii_control, timeout;
-
- if (au1000_debug > 4)
- printk("smsc_83C185_reset\n");
-
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
- mdelay(1);
- for (timeout = 100; timeout > 0; --timeout) {
- mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
- if ((mii_control & MII_CNTL_RESET) == 0)
- break;
- mdelay(1);
- }
- if (mii_control & MII_CNTL_RESET) {
- printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
- return -1;
- }
- return 0;
-}
-
-int
-smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- u16 mii_data;
- struct au1000_private *aup;
-
- if (!dev) {
- printk(KERN_ERR "smsc_83C185_status error: NULL dev\n");
- return -1;
- }
-
- aup = (struct au1000_private *) dev->priv;
- mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-
- if (mii_data & MII_STAT_LINK) {
- *link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, 0x1f);
- if (mii_data & (1<<3)) {
- if (mii_data & (1<<4)) {
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- }
- else {
- *speed = IF_PORT_100BASETX;
- dev->if_port = IF_PORT_100BASETX;
- }
- }
- else {
- *speed = IF_PORT_10BASET;
- dev->if_port = IF_PORT_10BASET;
- }
- }
- else {
- *link = 0;
- *speed = 0;
- dev->if_port = IF_PORT_UNKNOWN;
- }
- return 0;
-}
-
-
-#ifdef CONFIG_MIPS_BOSPORUS
-int stub_init(struct net_device *dev, int phy_addr)
-{
- //printk("PHY stub_init\n");
- return 0;
-}
-
-int stub_reset(struct net_device *dev, int phy_addr)
-{
- //printk("PHY stub_reset\n");
- return 0;
-}
-
-int
-stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
- //printk("PHY stub_status\n");
- *link = 1;
- /* hmmm, revisit */
- *speed = IF_PORT_100BASEFX;
- dev->if_port = IF_PORT_100BASEFX;
- return 0;
-}
-#endif
-
-struct phy_ops bcm_5201_ops = {
- bcm_5201_init,
- bcm_5201_reset,
- bcm_5201_status,
-};
-
-struct phy_ops am79c874_ops = {
- am79c874_init,
- am79c874_reset,
- am79c874_status,
-};
-
-struct phy_ops am79c901_ops = {
- am79c901_init,
- am79c901_reset,
- am79c901_status,
-};
-
-struct phy_ops lsi_80227_ops = {
- lsi_80227_init,
- lsi_80227_reset,
- lsi_80227_status,
-};
-
-struct phy_ops lxt971a_ops = {
- lxt971a_init,
- lxt971a_reset,
- lxt971a_status,
-};
+/* static PHY setup
+ *
+ * most boards PHY setup should be detectable properly with the
+ * autodetection algorithm in mii_probe(), but in some cases (e.g. if
+ * you have a switch attached, or want to use the PHY's interrupt
+ * notification capabilities) you can provide a static PHY
+ * configuration here
+ *
+ * IRQs may only be set, if a PHY address was configured
+ * If a PHY address is given, also a bus id is required to be set
+ *
+ * ps: make sure the used irqs are configured properly in the board
+ * specific irq-map
+ */
-struct phy_ops ks8995m_ops = {
- ks8995m_init,
- ks8995m_reset,
- ks8995m_status,
-};
+#if defined(CONFIG_MIPS_BOSPORUS)
+/*
+ * Micrel/Kendin 5 port switch attached to MAC0,
+ * MAC0 is associated with PHY address 5 (== WAN port)
+ * MAC1 is not associated with any PHY, since it's connected directly
+ * to the switch.
+ * no interrupts are used
+ */
+# define AU1XXX_PHY_STATIC_CONFIG
-struct phy_ops smsc_83C185_ops = {
- smsc_83C185_init,
- smsc_83C185_reset,
- smsc_83C185_status,
-};
+# define AU1XXX_PHY0_ADDR 5
+# define AU1XXX_PHY0_BUSID 0
+# undef AU1XXX_PHY0_IRQ
-#ifdef CONFIG_MIPS_BOSPORUS
-struct phy_ops stub_ops = {
- stub_init,
- stub_reset,
- stub_status,
-};
+# undef AU1XXX_PHY1_ADDR
+# undef AU1XXX_PHY1_BUSID
+# undef AU1XXX_PHY1_IRQ
#endif
-static struct mii_chip_info {
- const char * name;
- u16 phy_id0;
- u16 phy_id1;
- struct phy_ops *phy_ops;
- int dual_phy;
-} mii_chip_table[] = {
- {"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
- {"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
- {"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
- {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
- {"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
- {"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
- {"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
- {"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
- {"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
- {"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0},
-#ifdef CONFIG_MIPS_BOSPORUS
- {"Stub", 0x1234, 0x5678, &stub_ops },
+#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
+# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
#endif
- {0,},
-};
-static int mdio_read(struct net_device *dev, int phy_id, int reg)
+/*
+ * MII operations
+ */
+static int mdio_read(struct net_device *dev, int phy_addr, int reg)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
- volatile u32 *mii_control_reg;
- volatile u32 *mii_data_reg;
+ volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+ volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
u32 mii_control;
- #ifdef CONFIG_BCM5222_DUAL_PHY
- /* First time we probe, it's for the mac0 phy.
- * Since we haven't determined yet that we have a dual phy,
- * aup->mii->mii_control_reg won't be setup and we'll
- * default to the else statement.
- * By the time we probe for the mac1 phy, the mii_control_reg
- * will be setup to be the address of the mac0 phy control since
- * both phys are controlled through mac0.
- */
- if (aup->mii && aup->mii->mii_control_reg) {
- mii_control_reg = aup->mii->mii_control_reg;
- mii_data_reg = aup->mii->mii_data_reg;
- }
- else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
- /* assume both phys are controlled through mac0 */
- mii_control_reg = au_macs[0]->mii->mii_control_reg;
- mii_data_reg = au_macs[0]->mii->mii_data_reg;
- }
- else
- #endif
- {
- /* default control and data reg addresses */
- mii_control_reg = &aup->mac->mii_control;
- mii_data_reg = &aup->mac->mii_data;
- }
-
while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
@@ -835,7 +215,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
}
mii_control = MAC_SET_MII_SELECT_REG(reg) |
- MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;
+ MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
*mii_control_reg = mii_control;
@@ -851,32 +231,14 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
return (int)*mii_data_reg;
}
-static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
+static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
- volatile u32 *mii_control_reg;
- volatile u32 *mii_data_reg;
+ volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+ volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
u32 mii_control;
- #ifdef CONFIG_BCM5222_DUAL_PHY
- if (aup->mii && aup->mii->mii_control_reg) {
- mii_control_reg = aup->mii->mii_control_reg;
- mii_data_reg = aup->mii->mii_data_reg;
- }
- else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
- /* assume both phys are controlled through mac0 */
- mii_control_reg = au_macs[0]->mii->mii_control_reg;
- mii_data_reg = au_macs[0]->mii->mii_data_reg;
- }
- else
- #endif
- {
- /* default control and data reg addresses */
- mii_control_reg = &aup->mac->mii_control;
- mii_data_reg = &aup->mac->mii_data;
- }
-
while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
@@ -887,165 +249,145 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
}
mii_control = MAC_SET_MII_SELECT_REG(reg) |
- MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;
+ MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
*mii_data_reg = value;
*mii_control_reg = mii_control;
}
+static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+ /* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
+ * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
+ struct net_device *const dev = bus->priv;
+
+ enable_mac(dev, 0); /* make sure the MAC associated with this
+ * mii_bus is enabled */
+ return mdio_read(dev, phy_addr, regnum);
+}
-static void dump_mii(struct net_device *dev, int phy_id)
+static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 value)
{
- int i, val;
+ struct net_device *const dev = bus->priv;
- for (i = 0; i < 7; i++) {
- if ((val = mdio_read(dev, phy_id, i)) >= 0)
- printk("%s: MII Reg %d=%x\n", dev->name, i, val);
- }
- for (i = 16; i < 25; i++) {
- if ((val = mdio_read(dev, phy_id, i)) >= 0)
- printk("%s: MII Reg %d=%x\n", dev->name, i, val);
- }
+ enable_mac(dev, 0); /* make sure the MAC associated with this
+ * mii_bus is enabled */
+ mdio_write(dev, phy_addr, regnum, value);
+ return 0;
}
-static int mii_probe (struct net_device * dev)
+static int mdiobus_reset(struct mii_bus *bus)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
- int phy_addr;
-#ifdef CONFIG_MIPS_BOSPORUS
- int phy_found=0;
-#endif
+ struct net_device *const dev = bus->priv;
- /* search for total of 32 possible mii phy addresses */
- for (phy_addr = 0; phy_addr < 32; phy_addr++) {
- u16 mii_status;
- u16 phy_id0, phy_id1;
- int i;
+ enable_mac(dev, 0); /* make sure the MAC associated with this
+ * mii_bus is enabled */
+ return 0;
+}
- #ifdef CONFIG_BCM5222_DUAL_PHY
- /* Mask the already found phy, try next one */
- if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
- if (au_macs[0]->phy_addr == phy_addr)
- continue;
- }
- #endif
-
- mii_status = mdio_read(dev, phy_addr, MII_STATUS);
- if (mii_status == 0xffff || mii_status == 0x0000)
- /* the mii is not accessable, try next one */
- continue;
-
- phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);
- phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1);
-
- /* search our mii table for the current mii */
- for (i = 0; mii_chip_table[i].phy_id1; i++) {
- if (phy_id0 == mii_chip_table[i].phy_id0 &&
- phy_id1 == mii_chip_table[i].phy_id1) {
- struct mii_phy * mii_phy = aup->mii;
-
- printk(KERN_INFO "%s: %s at phy address %d\n",
- dev->name, mii_chip_table[i].name,
- phy_addr);
-#ifdef CONFIG_MIPS_BOSPORUS
- phy_found = 1;
-#endif
- mii_phy->chip_info = mii_chip_table+i;
- aup->phy_addr = phy_addr;
- aup->want_autoneg = 1;
- aup->phy_ops = mii_chip_table[i].phy_ops;
- aup->phy_ops->phy_init(dev,phy_addr);
-
- // Check for dual-phy and then store required
- // values and set indicators. We need to do
- // this now since mdio_{read,write} need the
- // control and data register addresses.
- #ifdef CONFIG_BCM5222_DUAL_PHY
- if ( mii_chip_table[i].dual_phy) {
-
- /* assume both phys are controlled
- * through MAC0. Board specific? */
-
- /* sanity check */
- if (!au_macs[0] || !au_macs[0]->mii)
- return -1;
- aup->mii->mii_control_reg = (u32 *)
- &au_macs[0]->mac->mii_control;
- aup->mii->mii_data_reg = (u32 *)
- &au_macs[0]->mac->mii_data;
- }
- #endif
- goto found;
- }
+static int mii_probe (struct net_device *dev)
+{
+ struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+ struct phy_device *phydev = NULL;
+
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+ BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
+
+ if(aup->mac_id == 0) { /* get PHY0 */
+# if defined(AU1XXX_PHY0_ADDR)
+ phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus.phy_map[AU1XXX_PHY0_ADDR];
+# else
+ printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+ dev->name);
+ return 0;
+# endif /* defined(AU1XXX_PHY0_ADDR) */
+ } else if (aup->mac_id == 1) { /* get PHY1 */
+# if defined(AU1XXX_PHY1_ADDR)
+ phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus.phy_map[AU1XXX_PHY1_ADDR];
+# else
+ printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+ dev->name);
+ return 0;
+# endif /* defined(AU1XXX_PHY1_ADDR) */
+ }
+
+#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */
+ 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 (aup->mii_bus.phy_map[phy_addr]) {
+ phydev = aup->mii_bus.phy_map[phy_addr];
+# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
+ break; /* break out with first one found */
+# endif
}
- }
-found:
-
-#ifdef CONFIG_MIPS_BOSPORUS
- /* This is a workaround for the Micrel/Kendin 5 port switch
- The second MAC doesn't see a PHY connected... so we need to
- trick it into thinking we have one.
-
- If this kernel is run on another Au1500 development board
- the stub will be found as well as the actual PHY. However,
- the last found PHY will be used... usually at Addr 31 (Db1500).
- */
- if ( (!phy_found) )
- {
- u16 phy_id0, phy_id1;
- int i;
- phy_id0 = 0x1234;
- phy_id1 = 0x5678;
-
- /* search our mii table for the current mii */
- for (i = 0; mii_chip_table[i].phy_id1; i++) {
- if (phy_id0 == mii_chip_table[i].phy_id0 &&
- phy_id1 == mii_chip_table[i].phy_id1) {
- struct mii_phy * mii_phy;
-
- printk(KERN_INFO "%s: %s at phy address %d\n",
- dev->name, mii_chip_table[i].name,
- phy_addr);
- mii_phy = kmalloc(sizeof(struct mii_phy),
- GFP_KERNEL);
- if (mii_phy) {
- mii_phy->chip_info = mii_chip_table+i;
- aup->phy_addr = phy_addr;
- mii_phy->next = aup->mii;
- aup->phy_ops =
- mii_chip_table[i].phy_ops;
- aup->mii = mii_phy;
- aup->phy_ops->phy_init(dev,phy_addr);
- } else {
- printk(KERN_ERR "%s: out of memory\n",
- dev->name);
- return -1;
- }
- mii_phy->chip_info = mii_chip_table+i;
- aup->phy_addr = phy_addr;
- aup->phy_ops = mii_chip_table[i].phy_ops;
- aup->phy_ops->phy_init(dev,phy_addr);
- break;
- }
+# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0)
+ /* try harder to find a PHY */
+ if (!phydev && (aup->mac_id == 1)) {
+ /* no PHY found, maybe we have a dual PHY? */
+ printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
+ "let's see if it's attached to MAC0...\n");
+
+ BUG_ON(!au_macs[0]);
+
+ /* find the first (lowest address) non-attached PHY on
+ * the MAC0 MII bus */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ struct phy_device *const tmp_phydev =
+ au_macs[0]->mii_bus.phy_map[phy_addr];
+
+ if (!tmp_phydev)
+ continue; /* no PHY here... */
+
+ if (tmp_phydev->attached_dev)
+ continue; /* already claimed by MAC0 */
+
+ phydev = tmp_phydev;
+ break; /* found it */
}
}
- if (aup->mac_id == 0) {
- /* the Bosporus phy responds to addresses 0-5 but
- * 5 is the correct one.
- */
- aup->phy_addr = 5;
- }
-#endif
+# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */
- if (aup->mii->chip_info == NULL) {
- printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
- dev->name);
+#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */
+ if (!phydev) {
+ printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name);
return -1;
}
- printk(KERN_INFO "%s: Using %s as default\n",
- dev->name, aup->mii->chip_info->name);
+ /* 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, &au1000_adjust_link, 0);
+
+ 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;
+
+ aup->old_link = 0;
+ aup->old_speed = 0;
+ aup->old_duplex = -1;
+ aup-