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
*
*
* ########################################################################
*
* 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.
*
* ########################################################################
*
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#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 <linux/cpu.h>
#include <linux/io.h>
#include <asm/mipsregs.h>
#include <asm/irq.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 AU1000_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
#define DRV_NAME "au1000_eth"
#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");
* 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.
*/
/*
* 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 au1000_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)) {
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
| MAC_EN_CLOCK_ENABLE), aup->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);
u32 *const mii_control_reg = &aup->mac->mii_control;
u32 *const mii_data_reg = &aup->mac->mii_data;
while (readl(mii_control_reg) & MAC_MII_BUSY) {
netdev_err(dev, "read_MII busy timeout!!\n");
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
writel(mii_control, mii_control_reg);
while (readl(mii_control_reg) & MAC_MII_BUSY) {
netdev_err(dev, "mdio_read busy timeout!!\n");
return readl(mii_data_reg);
Loading
Loading full blame...