Skip to content
Snippets Groups Projects
au1000_eth.c 32.7 KiB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
/*
 *
 * Alchemy Au1x00 ethernet driver
 *
 * Copyright 2001-2003, 2006 MontaVista Software Inc.
Linus Torvalds's avatar
Linus Torvalds committed
 * 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
Linus Torvalds's avatar
Linus Torvalds committed
 * ioctls (SIOCGMIIPHY)
 * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
 *  converted to use linux-2.6.x's PHY framework
 *
Linus Torvalds's avatar
Linus Torvalds committed
 * 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.
 *
 * ########################################################################
 *
Linus Torvalds's avatar
Linus Torvalds committed
 */
Ralf Baechle's avatar
Ralf Baechle committed
#include <linux/dma-mapping.h>
Linus Torvalds's avatar
Linus Torvalds committed
#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>
Yoichi Yuasa's avatar
Yoichi Yuasa committed

#include <asm/cpu.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/processor.h>

Yoichi Yuasa's avatar
Yoichi Yuasa committed
#include <au1000.h>
#include <prom.h>

Linus Torvalds's avatar
Linus Torvalds committed
#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"
Linus Torvalds's avatar
Linus Torvalds committed
#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
Linus Torvalds's avatar
Linus Torvalds committed
 * hardware registers.
 *
 * Since the Au1000 has a coherent data cache, the receive and
 * transmit buffers are allocated from the KSEG0 segment. The
Linus Torvalds's avatar
Linus Torvalds committed
 * 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 = {
Linus Torvalds's avatar
Linus Torvalds committed
	0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
};

struct au1000_private *au_macs[NUM_ETH_INTERFACES];

/*
 * 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.
Linus Torvalds's avatar
Linus Torvalds committed
 */

/* autodetection defaults */
#undef  AU1XXX_PHY_SEARCH_HIGHEST_ADDR
#define AU1XXX_PHY1_SEARCH_ON_MAC0
Linus Torvalds's avatar
Linus Torvalds committed

/* 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
 */
Linus Torvalds's avatar
Linus Torvalds committed

#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
Linus Torvalds's avatar
Linus Torvalds committed

# define AU1XXX_PHY0_ADDR  5
# define AU1XXX_PHY0_BUSID 0
#  undef AU1XXX_PHY0_IRQ
Linus Torvalds's avatar
Linus Torvalds committed

#  undef AU1XXX_PHY1_ADDR
#  undef AU1XXX_PHY1_BUSID
#  undef AU1XXX_PHY1_IRQ
Linus Torvalds's avatar
Linus Torvalds committed
#endif

#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
Linus Torvalds's avatar
Linus Torvalds committed
#endif

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);
}

static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
Linus Torvalds's avatar
Linus Torvalds committed
{
	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;
Loading
Loading full blame...