/*
* Ethernet driver for the Atmel AT91RM9200 (Thunder)
*
* Copyright (C) 2003 SAN People (Pty) Ltd
*
* Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
* Initial version by Rick Bronson 01/11/2003
*
* Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
* (Polaroid Corporation)
*
* Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/dma-mapping.h>
#include <linux/ethtool.h>
#include <linux/platform_data/macb.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/gfp.h>
#include <linux/phy.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/mach-types.h>
#include <mach/at91rm9200_emac.h>
#include <asm/gpio.h>
#include <mach/board.h>
#include "at91_ether.h"
#define DRV_NAME "at91_ether"
#define DRV_VERSION "1.0"
#define LINK_POLL_INTERVAL (HZ)
/* ..................................................................... */
/*
* Read from a EMAC register.
*/
static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
{
return __raw_readl(lp->emac_base + reg);
}
/*
* Write to a EMAC register.
*/
static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
{
__raw_writel(value, lp->emac_base + reg);
}
/* ........................... PHY INTERFACE ........................... */
/*
* Enable the MDIO bit in MAC control register
* When not called from an interrupt-handler, access to the PHY must be
* protected by a spinlock.
*/
static void enable_mdi(struct at91_private *lp)
{
unsigned long ctl;
ctl = at91_emac_read(lp, AT91_EMAC_CTL);
at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
}
/*
* Disable the MDIO bit in the MAC control register
*/
static void disable_mdi(struct at91_private *lp)
{
unsigned long ctl;
ctl = at91_emac_read(lp, AT91_EMAC_CTL);
at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
}
/*
* Wait until the PHY operation is complete.
*/
static inline void at91_phy_wait(struct at91_private *lp)
{
unsigned long timeout = jiffies + 2;
while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
if (time_after(jiffies, timeout)) {
printk("at91_ether: MIO timeout\n");
break;
}
cpu_relax();
}
}
/*
* Write value to the a PHY register