Newer
Older
* Copyright 2001-2003, 2006 MontaVista Software Inc.
* Copyright 2002 TimeSys Corp.
* Added ethtool/mii-tool support,
* Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
* Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de
* or riemer@riemer-nt.de: fixed the link beat detection with
* 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
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/ioport.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <au1xxx_eth.h>
#include "au1000_eth.h"
#ifdef AU1000_ETH_DEBUG
static int au1000_debug = 5;
#else
static int au1000_debug = 3;
#endif
#define DRV_NAME "au1000_eth"
#define DRV_VERSION "1.6"
#define DRV_AUTHOR "Pete Popov <ppopov@embeddedalley.com>"
#define DRV_DESC "Au1xxx on-chip Ethernet driver"
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");
/*
* Theory of operation
*
* The Au1000 MACs use a simple rx and tx descriptor ring scheme.
* There are four receive and four transmit descriptors. These
* descriptors are not in memory; rather, they are just a set of
* hardware registers.
*
* Since the Au1000 has a coherent data cache, the receive and
* transmit buffers are allocated from the KSEG0 segment. The
* hardware registers, however, are still mapped at KSEG1 to
* make sure there's no out-of-order writes, and that all writes
* complete immediately.
*/
/* These addresses are only used if yamon doesn't tell us what
* the mac address is, and the mac address is not passed on the
* command line.
*/
static unsigned char au1000_mac_addr[6] __devinitdata = {
0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
};
struct au1000_private *au_macs[NUM_ETH_INTERFACES];
/*
* board-specific configurations
*
* PHY detection algorithm
*
* If 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 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 phy1_search_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.
/* autodetection defaults: phy1_search_mac0 */
/* 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
*/
static void enable_mac(struct net_device *dev, int force_reset)
{
unsigned long flags;
struct au1000_private *aup = netdev_priv(dev);
spin_lock_irqsave(&aup->lock, flags);
if(force_reset || (!aup->mac_enabled)) {
*aup->enable = MAC_EN_CLOCK_ENABLE;
au_sync_delay(2);
*aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
| MAC_EN_CLOCK_ENABLE);
au_sync_delay(2);
aup->mac_enabled = 1;
}
spin_unlock_irqrestore(&aup->lock, flags);
}
/*
* MII operations
*/
static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
struct au1000_private *aup = netdev_priv(dev);
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;
while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
printk(KERN_ERR "%s: read_MII busy timeout!!\n",
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
*mii_control_reg = mii_control;
timedout = 20;
while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
printk(KERN_ERR "%s: mdio_read busy timeout!!\n",
Loading
Loading full blame...