9
0
Fork 0

svn_rev_573

cleanups, generic phy support
This commit is contained in:
Sascha Hauer 2007-07-05 18:02:06 +02:00 committed by Sascha Hauer
parent 14edc91f97
commit 955ed9aae1
2 changed files with 50 additions and 233 deletions

View File

@ -15,6 +15,7 @@
#include <driver.h>
#include <asm/arch/sdma.h>
#include <asm/arch/fec.h>
#include <mii_phy.h>
#include "fec_mpc5200.h"
DECLARE_GLOBAL_DATA_PTR;
@ -27,10 +28,6 @@ static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec);
static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec);
#endif /* DEBUG */
#if (DEBUG & 0x40)
static uint32 local_crc32(char *string, unsigned int crc_value, int len);
#endif
typedef struct {
uint8 data[1500]; /* actual data */
int length; /* actual length */
@ -38,8 +35,8 @@ typedef struct {
uint8 head[16]; /* MAC header(6 + 6 + 2) + 2(aligned) */
} NBUF;
int fec5xxx_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
int fec5xxx_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
static int fec5xxx_miiphy_read(struct miiphy_device *mdev, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
static int fec5xxx_miiphy_write(struct miiphy_device *mdev, uint8 phyAddr, uint8 regAddr, uint16 data);
/********************************************************************/
static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
@ -261,7 +258,6 @@ static int mpc5xxx_fec_init(struct eth_device *dev)
fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
}
fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
if (fec->xcv_type != SEVENWIRE) {
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
@ -314,14 +310,6 @@ static int mpc5xxx_fec_init(struct eth_device *dev)
*/
fec->eth->xmit_fsm = 0x03000000;
#if defined(CONFIG_MPC5200)
/*
* Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
* work w/ the current receive task.
*/
sdma->PtdCntrl |= 0x00000001;
#endif
/*
* Set priority of different initiators
*/
@ -342,173 +330,48 @@ static int mpc5xxx_fec_init(struct eth_device *dev)
*(volatile int *)FEC_TBD_NEXT = (int)fec->tbdBase;
*(volatile int *)FEC_RBD_NEXT = (int)fec->rbdBase;
#if (DEBUG & 0x1)
printf("mpc5xxx_fec_init... Done \n");
#endif
if (fec->xcv_type != SEVENWIRE)
miiphy_restart_aneg(&fec->miiphy);
return 0;
}
static int mpc5xxx_fec_open(struct eth_device *edev)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)edev->priv;
#if defined(CONFIG_MPC5200)
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
/*
* Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
* work w/ the current receive task.
*/
sdma->PtdCntrl |= 0x00000001;
#endif
fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
/*
* Enable FEC-Lite controller
*/
fec->eth->ecntrl |= 0x00000006;
#if (DEBUG & 0x2)
if (fec->xcv_type != SEVENWIRE)
mpc5xxx_fec_phydump ();
#endif
/*
* Enable SmartDMA receive task
*/
SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
#if (DEBUG & 0x1)
printf("mpc5xxx_fec_init... Done \n");
#endif
if (fec->xcv_type != SEVENWIRE) {
miiphy_wait_aneg(&fec->miiphy);
miiphy_print_status(&fec->miiphy);
}
return 0;
}
/********************************************************************/
static int mpc5xxx_fec_init_phy(struct eth_device *dev)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
const uint8 phyAddr = CONFIG_PHY_ADDR; /* Only one PHY */
#if (DEBUG & 0x1)
printf ("mpc5xxx_fec_init_phy... Begin\n");
#endif
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
fec->eth->ievent = 0xffffffff;
/*
* Set interrupt mask register
*/
fec->eth->imask = 0x00000000;
if (fec->xcv_type != SEVENWIRE) {
int timeout = 1;
uint16 phyStatus;
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); /* No MII for 7-wire mode */
/*
* Initialize PHY(LXT971A):
*
* Generally, on power up, the LXT971A reads its configuration
* pins to check for forced operation, If not cofigured for
* forced operation, it uses auto-negotiation/parallel detection
* to automatically determine line operating conditions.
* If the PHY device on the other side of the link supports
* auto-negotiation, the LXT971A auto-negotiates with it
* using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
* support auto-negotiation, the LXT971A automatically detects
* the presence of either link pulses(10Mbps PHY) or Idle
* symbols(100Mbps) and sets its operating conditions accordingly.
*
* When auto-negotiation is controlled by software, the following
* steps are recommended.
*
* Note:
* The physical address is dependent on hardware configuration.
*
*/
/*
* Reset PHY, then delay 300ns
*/
miiphy_write(dev->name, phyAddr, 0x0, 0x8000);
udelay(1000);
if (fec->xcv_type == MII10) {
/*
* Force 10Base-T, FDX operation
*/
printf("Forcing 10 Mbps ethernet link... ");
miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
/*
miiphy_write(dev->name, fec, phyAddr, 0x0, 0x0100);
*/
miiphy_write(dev->name, phyAddr, 0x0, 0x0180);
timeout = 20;
do { /* wait for link status to go down */
udelay(10000);
if ((timeout--) == 0) {
#if (DEBUG & 0x2)
printf("hmmm, should not have waited...");
#endif
break;
}
miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf("=");
#endif
} while ((phyStatus & 0x0004)); /* !link up */
timeout = 1000;
do { /* wait for link status to come back up */
udelay(10000);
if ((timeout--) == 0) {
printf("failed. Link is down.\n");
break;
}
miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf("+");
#endif
} while (!(phyStatus & 0x0004)); /* !link up */
printf ("done.\n");
} else { /* MII100 */
/*
* Set the auto-negotiation advertisement register bits
*/
miiphy_write(dev->name, phyAddr, 0x4, 0x01e1);
/*
* Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
*/
miiphy_write(dev->name, phyAddr, 0x0, 0x1200);
/*
* Wait for AN completion
*/
timeout = 5000;
do {
udelay(1000);
if ((timeout--) == 0) {
printf("PHY auto neg 0 failed...\n");
return -1;
}
if (miiphy_read(dev->name, phyAddr, 0x1, &phyStatus) != 0) {
printf("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
return -1;
}
} while (!(phyStatus & 0x0004));
printf("PHY auto neg complete! \n");
}
}
#if (DEBUG & 0x2)
if (fec->xcv_type != SEVENWIRE)
mpc5xxx_fec_phydump (dev->name);
#endif
#if (DEBUG & 0x1)
printf("mpc5xxx_fec_init_phy... Done \n");
#endif
return 1;
}
/********************************************************************/
static void mpc5xxx_fec_halt(struct eth_device *dev)
{
#if defined(CONFIG_MPC5200)
@ -522,11 +385,6 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
mpc5xxx_fec_phydump ();
#endif
/*
* mask FEC chip interrupts
*/
fec->eth->imask = 0;
/*
* issue graceful stop command to the FEC transmitter if necessary
*/
@ -562,17 +420,7 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
fec->eth->rfifo_status &= 0x00700000;
fec->eth->tfifo_status &= 0x00700000;
fec->eth->reset_cntrl = 0x01000000;
/*
* Issue a reset command to the FEC chip
*/
fec->eth->ecntrl |= 0x1;
/*
* wait at least 16 clock cycles
*/
udelay(10);
// fec->eth->reset_cntrl = 0x01000000;
#if (DEBUG & 0x3)
printf("Ethernet task stopped\n");
@ -590,7 +438,7 @@ static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
|| (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
miiphy_read(devname, phyAddr, 0x1, &phyStatus);
fec5xxx_miiphy_read(devname, phyAddr, 0x1, &phyStatus);
printf("\nphyStatus: 0x%04x\n", phyStatus);
printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
printf("ievent: 0x%08x\n", fec->eth->ievent);
@ -614,7 +462,7 @@ static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
|| (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
miiphy_read(devname, phyAddr, 0x1, &phyStatus);
fec5xxx_miiphy_read(devname, phyAddr, 0x1, &phyStatus);
printf("\nphyStatus: 0x%04x\n", phyStatus);
printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
printf("ievent: 0x%08x\n", fec->eth->ievent);
@ -688,7 +536,7 @@ static int mpc5xxx_fec_send(struct eth_device *dev, void *eth_data,
*/
if (fec->xcv_type != SEVENWIRE) {
uint16 phyStatus;
miiphy_read(dev->name, 0, 0x1, &phyStatus);
fec5xxx_miiphy_read(&fec->miiphy, 0, 0x1, &phyStatus);
}
/*
@ -806,7 +654,6 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
return len;
}
/********************************************************************/
int mpc5xxx_fec_probe(struct device_d *dev)
{
@ -819,7 +666,8 @@ int mpc5xxx_fec_probe(struct device_d *dev)
fec = (mpc5xxx_fec_priv *)malloc(sizeof(*fec));
edev->priv = fec;
edev->dev = dev;
edev->open = mpc5xxx_fec_init,
edev->open = mpc5xxx_fec_open,
edev->init = mpc5xxx_fec_init,
edev->send = mpc5xxx_fec_send,
edev->recv = mpc5xxx_fec_recv,
edev->halt = mpc5xxx_fec_halt,
@ -834,21 +682,22 @@ int mpc5xxx_fec_probe(struct device_d *dev)
sprintf(dev->name, "FEC ETHERNET");
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
miiphy_register (dev->name,
fec5xxx_miiphy_read, fec5xxx_miiphy_write);
#endif
if (fec->xcv_type != SEVENWIRE) {
fec->miiphy.read = fec5xxx_miiphy_read;
fec->miiphy.write = fec5xxx_miiphy_write;
fec->miiphy.address = CONFIG_PHY_ADDR;
fec->miiphy.flags = pdata->xcv_type == MII10 ? MIIPHY_FORCE_10 : 0;
eth_register(edev);
mpc5xxx_fec_init_phy(edev);
miiphy_register(&fec->miiphy);
}
eth_register(edev);
return 0;
}
/* MII-interface related functions */
/********************************************************************/
int miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
static int fec5xxx_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr, uint8_t regAddr, uint16_t * retVal)
{
ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
uint32 reg; /* convenient holder for the PHY register */
@ -890,7 +739,7 @@ int miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
}
/********************************************************************/
int miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
static int fec5xxx_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
{
ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
uint32 reg; /* convenient holder for the PHY register */
@ -923,41 +772,6 @@ int miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
return 0;
}
#if (DEBUG & 0x40)
static uint32 local_crc32(char *string, unsigned int crc_value, int len)
{
int i;
char c;
unsigned int crc, count;
/*
* crc32 algorithm
*/
/*
* crc = 0xffffffff; * The initialized value should be 0xffffffff
*/
crc = crc_value;
for (i = len; --i >= 0;) {
c = *string++;
for (count = 0; count < 8; count++) {
if ((c & 0x01) ^ (crc & 0x01)) {
crc >>= 1;
crc = crc ^ 0xedb88320;
} else {
crc >>= 1;
}
c >>= 1;
}
}
/*
* In big endian system, do byte swaping for crc value
*/
/**/ return crc;
}
#endif /* DEBUG */
static struct driver_d mpc5xxx_driver = {
.name = "fec_mpc5xxx",
.probe = mpc5xxx_fec_probe,

View File

@ -14,6 +14,7 @@
#include <common.h>
#include <mpc5xxx.h>
#include <asm/arch/sdma.h>
#include <mii_phy.h>
typedef unsigned long uint32;
typedef unsigned short uint16;
@ -226,6 +227,8 @@ typedef struct {
uint16 tbdIndex; /* next transmit BD to send */
uint16 usedTbdIndex; /* next transmit BD to clean */
uint16 cleanTbdNum; /* the number of available transmit BDs */
struct miiphy_device miiphy;
} mpc5xxx_fec_priv;
/* Ethernet parameter area */