|
|
|
@ -38,72 +38,79 @@ |
|
|
|
|
* Utility to send the preamble, address, and register (common to read |
|
|
|
|
* and write). |
|
|
|
|
*/ |
|
|
|
|
static void miiphy_pre(char read, |
|
|
|
|
unsigned char addr, |
|
|
|
|
unsigned char reg) |
|
|
|
|
static void miiphy_pre (char read, unsigned char addr, unsigned char reg) |
|
|
|
|
{ |
|
|
|
|
int j; /* counter */ |
|
|
|
|
volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. |
|
|
|
|
* The IEEE spec says this is a PHY optional requirement. The AMD |
|
|
|
|
* 79C874 requires one after power up and one after a MII communications |
|
|
|
|
* error. This means that we are doing more preambles than we need, |
|
|
|
|
* but it is safer and will be much more robust. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
MDIO_ACTIVE; |
|
|
|
|
MDIO(1); |
|
|
|
|
for(j = 0; j < 32; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* send the start bit (01) and the read opcode (10) or write (10) */ |
|
|
|
|
MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
MDC(0); MDIO(read); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
MDC(0); MDIO(!read); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* send the PHY address */ |
|
|
|
|
for(j = 0; j < 5; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(0); |
|
|
|
|
if((addr & 0x10) == 0) |
|
|
|
|
{ |
|
|
|
|
MDIO(0); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
MDIO(1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
addr <<= 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* send the register address */ |
|
|
|
|
for(j = 0; j < 5; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(0); |
|
|
|
|
if((reg & 0x10) == 0) |
|
|
|
|
{ |
|
|
|
|
MDIO(0); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
MDIO(1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
reg <<= 1; |
|
|
|
|
} |
|
|
|
|
int j; /* counter */ |
|
|
|
|
#ifndef CONFIG_EP8248 |
|
|
|
|
volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. |
|
|
|
|
* The IEEE spec says this is a PHY optional requirement. The AMD |
|
|
|
|
* 79C874 requires one after power up and one after a MII communications |
|
|
|
|
* error. This means that we are doing more preambles than we need, |
|
|
|
|
* but it is safer and will be much more robust. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
MDIO_ACTIVE; |
|
|
|
|
MDIO (1); |
|
|
|
|
for (j = 0; j < 32; j++) { |
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* send the start bit (01) and the read opcode (10) or write (10) */ |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (read); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (!read); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* send the PHY address */ |
|
|
|
|
for (j = 0; j < 5; j++) { |
|
|
|
|
MDC (0); |
|
|
|
|
if ((addr & 0x10) == 0) { |
|
|
|
|
MDIO (0); |
|
|
|
|
} else { |
|
|
|
|
MDIO (1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
addr <<= 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* send the register address */ |
|
|
|
|
for (j = 0; j < 5; j++) { |
|
|
|
|
MDC (0); |
|
|
|
|
if ((reg & 0x10) == 0) { |
|
|
|
|
MDIO (0); |
|
|
|
|
} else { |
|
|
|
|
MDIO (1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
reg <<= 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -114,66 +121,63 @@ static void miiphy_pre(char read, |
|
|
|
|
* Returns: |
|
|
|
|
* 0 on success |
|
|
|
|
*/ |
|
|
|
|
int miiphy_read(unsigned char addr, |
|
|
|
|
unsigned char reg, |
|
|
|
|
unsigned short *value) |
|
|
|
|
int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value) |
|
|
|
|
{ |
|
|
|
|
short rdreg; /* register working value */ |
|
|
|
|
int j; /* counter */ |
|
|
|
|
volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); |
|
|
|
|
|
|
|
|
|
miiphy_pre(1, addr, reg); |
|
|
|
|
|
|
|
|
|
/* tri-state our MDIO I/O pin so we can read */ |
|
|
|
|
MDC(0); |
|
|
|
|
MDIO_TRISTATE; |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* check the turnaround bit: the PHY should be driving it to zero */ |
|
|
|
|
if(MDIO_READ != 0) |
|
|
|
|
{ |
|
|
|
|
/* puts ("PHY didn't drive TA low\n"); */ |
|
|
|
|
for(j = 0; j < 32; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
return(-1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* read 16 bits of register data, MSB first */ |
|
|
|
|
rdreg = 0; |
|
|
|
|
for(j = 0; j < 16; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
rdreg <<= 1; |
|
|
|
|
rdreg |= MDIO_READ; |
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
*value = rdreg; |
|
|
|
|
short rdreg; /* register working value */ |
|
|
|
|
int j; /* counter */ |
|
|
|
|
#ifndef CONFIG_EP8248 |
|
|
|
|
volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
miiphy_pre (1, addr, reg); |
|
|
|
|
|
|
|
|
|
/* tri-state our MDIO I/O pin so we can read */ |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO_TRISTATE; |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* check the turnaround bit: the PHY should be driving it to zero */ |
|
|
|
|
if (MDIO_READ != 0) { |
|
|
|
|
/* puts ("PHY didn't drive TA low\n"); */ |
|
|
|
|
for (j = 0; j < 32; j++) { |
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
return (-1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* read 16 bits of register data, MSB first */ |
|
|
|
|
rdreg = 0; |
|
|
|
|
for (j = 0; j < 16; j++) { |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
rdreg <<= 1; |
|
|
|
|
rdreg |= MDIO_READ; |
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
*value = rdreg; |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); |
|
|
|
|
printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -184,47 +188,51 @@ int miiphy_read(unsigned char addr, |
|
|
|
|
* Returns: |
|
|
|
|
* 0 on success |
|
|
|
|
*/ |
|
|
|
|
int miiphy_write(unsigned char addr, |
|
|
|
|
unsigned char reg, |
|
|
|
|
unsigned short value) |
|
|
|
|
int miiphy_write (unsigned char addr, unsigned char reg, unsigned short value) |
|
|
|
|
{ |
|
|
|
|
int j; /* counter */ |
|
|
|
|
volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); |
|
|
|
|
|
|
|
|
|
miiphy_pre(0, addr, reg); |
|
|
|
|
|
|
|
|
|
/* send the turnaround (10) */ |
|
|
|
|
MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* write 16 bits of register data, MSB first */ |
|
|
|
|
for(j = 0; j < 16; j++) |
|
|
|
|
{ |
|
|
|
|
MDC(0); |
|
|
|
|
if((value & 0x00008000) == 0) |
|
|
|
|
{ |
|
|
|
|
MDIO(0); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
MDIO(1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
value <<= 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tri-state the MDIO line. |
|
|
|
|
*/ |
|
|
|
|
MDIO_TRISTATE; |
|
|
|
|
MDC(0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC(1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
int j; /* counter */ |
|
|
|
|
#ifndef CONFIG_EP8248 |
|
|
|
|
volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
miiphy_pre (0, addr, reg); |
|
|
|
|
|
|
|
|
|
/* send the turnaround (10) */ |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (0); |
|
|
|
|
MDIO (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
/* write 16 bits of register data, MSB first */ |
|
|
|
|
for (j = 0; j < 16; j++) { |
|
|
|
|
MDC (0); |
|
|
|
|
if ((value & 0x00008000) == 0) { |
|
|
|
|
MDIO (0); |
|
|
|
|
} else { |
|
|
|
|
MDIO (1); |
|
|
|
|
} |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
value <<= 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tri-state the MDIO line. |
|
|
|
|
*/ |
|
|
|
|
MDIO_TRISTATE; |
|
|
|
|
MDC (0); |
|
|
|
|
MIIDELAY; |
|
|
|
|
MDC (1); |
|
|
|
|
MIIDELAY; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif /* CONFIG_BITBANGMII */ |
|
|
|
|