mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 15:37:23 +00:00
Blackfin: bfin_mac: cleanup MII/PHY functions
Cleanup and rewrite the MII/PHY related functions so that we can reuse the existing common linux/miiphy.h code and hook into the `mii` command. Signed-off-by: Mike Frysinger <vapier@gentoo.org> Acked-by: Ben Warren <biggerbadderben@gmail.com>
This commit is contained in:
parent
6b310a05f0
commit
ac45af4e63
2 changed files with 134 additions and 175 deletions
|
@ -12,6 +12,8 @@
|
|||
#include <netdev.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <miiphy.h>
|
||||
#include <linux/mii.h>
|
||||
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/mach-common/bits/dma.h>
|
||||
|
@ -43,8 +45,6 @@ ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
|
|||
static u16 txIdx; /* index of the current RX buffer */
|
||||
static u16 rxIdx; /* index of the current TX buffer */
|
||||
|
||||
u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */
|
||||
|
||||
/* DMAx_CONFIG values at DMA Restart */
|
||||
const ADI_DMA_CONFIG_REG rxdmacfg = {
|
||||
.b_DMA_EN = 1, /* enabled */
|
||||
|
@ -70,10 +70,38 @@ const ADI_DMA_CONFIG_REG txdmacfg = {
|
|||
.b_FLOW = 7 /* large desc flow */
|
||||
};
|
||||
|
||||
static int bfin_miiphy_wait(void)
|
||||
{
|
||||
/* poll the STABUSY bit */
|
||||
while (bfin_read_EMAC_STAADD() & STABUSY)
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_miiphy_read(char *devname, uchar addr, uchar reg, ushort *val)
|
||||
{
|
||||
if (bfin_miiphy_wait())
|
||||
return 1;
|
||||
bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
|
||||
if (bfin_miiphy_wait())
|
||||
return 1;
|
||||
*val = bfin_read_EMAC_STADAT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_miiphy_write(char *devname, uchar addr, uchar reg, ushort val)
|
||||
{
|
||||
if (bfin_miiphy_wait())
|
||||
return 1;
|
||||
bfin_write_EMAC_STADAT(val);
|
||||
bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STAOP | STABUSY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bfin_EMAC_initialize(bd_t *bis)
|
||||
{
|
||||
struct eth_device *dev;
|
||||
dev = (struct eth_device *)malloc(sizeof(*dev));
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (dev == NULL)
|
||||
hang();
|
||||
|
||||
|
@ -89,6 +117,10 @@ int bfin_EMAC_initialize(bd_t *bis)
|
|||
|
||||
eth_register(dev);
|
||||
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -182,6 +214,100 @@ static int bfin_EMAC_recv(struct eth_device *dev)
|
|||
*
|
||||
*************************************************************/
|
||||
|
||||
/* MDC = SCLK / MDC_freq / 2 - 1 */
|
||||
#define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
|
||||
|
||||
static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
|
||||
{
|
||||
u16 phydat;
|
||||
size_t count;
|
||||
|
||||
/* Enable PHY output */
|
||||
*pVR_CTL |= CLKBUFOE;
|
||||
|
||||
/* Set all the pins to peripheral mode */
|
||||
#ifdef CONFIG_BFIN_MAC_RMII
|
||||
/* grab RMII pins */
|
||||
# if defined(__ADSPBF51x__)
|
||||
*pPORTF_MUX = (*pPORTF_MUX & \
|
||||
~(PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
|
||||
PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
|
||||
*pPORTF_FER |= PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
|
||||
*pPORTG_FER |= PG0 | PG1 | PG2;
|
||||
# elif defined(__ADSPBF52x__)
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
|
||||
*pPORTG_FER |= PG14 | PG15;
|
||||
*pPORTH_MUX = (*pPORTH_MUX & ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK)) | \
|
||||
PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2;
|
||||
*pPORTH_FER |= PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8;
|
||||
# else
|
||||
*pPORTH_FER |= PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15;
|
||||
# endif
|
||||
#else
|
||||
/* grab MII & RMII pins */
|
||||
# if defined(__ADSPBF51x__)
|
||||
*pPORTF_MUX = (*pPORTF_MUX & \
|
||||
~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
|
||||
PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
|
||||
*pPORTF_FER |= PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
|
||||
*pPORTG_FER |= PG0 | PG1 | PG2;
|
||||
# elif defined(__ADSPBF52x__)
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
|
||||
*pPORTG_FER |= PG14 | PG15;
|
||||
*pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2;
|
||||
*pPORTH_FER = -1; /* all pins */
|
||||
# else
|
||||
*pPORTH_FER = -1; /* all pins */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Odd word alignment for Receive Frame DMA word */
|
||||
/* Configure checksum support and rcve frame word alignment */
|
||||
bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(2500000)));
|
||||
|
||||
/* turn on auto-negotiation and wait for link to come up */
|
||||
bfin_miiphy_write(dev->name, PHYADDR, MII_BMCR, BMCR_ANENABLE);
|
||||
count = 0;
|
||||
while (1) {
|
||||
++count;
|
||||
if (bfin_miiphy_read(dev->name, PHYADDR, MII_BMSR, &phydat))
|
||||
return -1;
|
||||
if (phydat & BMSR_LSTATUS)
|
||||
break;
|
||||
if (count > 30000) {
|
||||
printf("%s: link down, check cable\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
/* see what kind of link we have */
|
||||
if (bfin_miiphy_read(dev->name, PHYADDR, MII_LPA, &phydat))
|
||||
return -1;
|
||||
if (phydat & LPA_DUPLEX)
|
||||
*opmode = FDMODE;
|
||||
else
|
||||
*opmode = 0;
|
||||
|
||||
bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
|
||||
|
||||
/* Initialize the TX DMA channel registers */
|
||||
*pDMA2_X_COUNT = 0;
|
||||
*pDMA2_X_MODIFY = 4;
|
||||
*pDMA2_Y_COUNT = 0;
|
||||
*pDMA2_Y_MODIFY = 0;
|
||||
|
||||
/* Initialize the RX DMA channel registers */
|
||||
*pDMA1_X_COUNT = 0;
|
||||
*pDMA1_X_MODIFY = 4;
|
||||
*pDMA1_Y_COUNT = 0;
|
||||
*pDMA1_Y_MODIFY = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
|
||||
{
|
||||
u32 opmode;
|
||||
|
@ -192,14 +318,14 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
|
|||
txIdx = 0;
|
||||
rxIdx = 0;
|
||||
|
||||
/* Initialize System Register */
|
||||
if (SetupSystemRegs(&dat) < 0)
|
||||
/* Initialize System Register */
|
||||
if (bfin_miiphy_init(dev, &dat) < 0)
|
||||
return -1;
|
||||
|
||||
/* Initialize EMAC address */
|
||||
/* Initialize EMAC address */
|
||||
bfin_EMAC_setup_addr(bd);
|
||||
|
||||
/* Initialize TX and RX buffer */
|
||||
/* Initialize TX and RX buffer */
|
||||
for (i = 0; i < PKTBUFSRX; i++) {
|
||||
rxbuf[i] = SetupRxBuffer(i);
|
||||
if (i > 0) {
|
||||
|
@ -226,7 +352,7 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
|
|||
*pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG);
|
||||
|
||||
/* Wait MII done */
|
||||
PollMdcDone();
|
||||
bfin_miiphy_wait();
|
||||
|
||||
/* We enable only RX here */
|
||||
/* ASTP : Enable Automatic Pad Stripping
|
||||
|
@ -271,148 +397,6 @@ void bfin_EMAC_setup_addr(bd_t *bd)
|
|||
bd->bi_enetaddr[5] << 8;
|
||||
}
|
||||
|
||||
static void PollMdcDone(void)
|
||||
{
|
||||
/* poll the STABUSY bit */
|
||||
while (*pEMAC_STAADD & STABUSY) ;
|
||||
}
|
||||
|
||||
static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data)
|
||||
{
|
||||
PollMdcDone();
|
||||
|
||||
*pEMAC_STADAT = Data;
|
||||
|
||||
*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
|
||||
STAOP | STAIE | STABUSY;
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* Read an off-chip register in a PHY through the MDC/MDIO port *
|
||||
*********************************************************************************/
|
||||
static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr)
|
||||
{
|
||||
u16 Data;
|
||||
|
||||
PollMdcDone();
|
||||
|
||||
*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
|
||||
STAIE | STABUSY;
|
||||
|
||||
PollMdcDone();
|
||||
|
||||
Data = (u16) * pEMAC_STADAT;
|
||||
|
||||
PHYregs[RegAddr] = Data; /* save shadow copy */
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
#if 0 /* dead code ? */
|
||||
static void SoftResetPHY(void)
|
||||
{
|
||||
u16 phydat;
|
||||
/* set the reset bit */
|
||||
WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET);
|
||||
/* and clear it again */
|
||||
WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000);
|
||||
do {
|
||||
/* poll until reset is complete */
|
||||
phydat = RdPHYReg(PHYADDR, PHY_MODECTL);
|
||||
} while ((phydat & PHY_RESET) != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* MDC = SCLK / MDC_freq / 2 - 1 */
|
||||
#define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
|
||||
|
||||
static int SetupSystemRegs(int *opmode)
|
||||
{
|
||||
u16 phydat;
|
||||
int count = 0;
|
||||
/* Enable PHY output */
|
||||
*pVR_CTL |= CLKBUFOE;
|
||||
/* Set all the pins to peripheral mode */
|
||||
|
||||
#ifdef CONFIG_BFIN_MAC_RMII
|
||||
/* grab RMII pins */
|
||||
# if defined(__ADSPBF51x__)
|
||||
*pPORTF_MUX = (*pPORTF_MUX & \
|
||||
~(PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
|
||||
PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
|
||||
*pPORTF_FER |= PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
|
||||
*pPORTG_FER |= PG0 | PG1 | PG2;
|
||||
# elif defined(__ADSPBF52x__)
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
|
||||
*pPORTG_FER |= PG14 | PG15;
|
||||
*pPORTH_MUX = (*pPORTH_MUX & ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK)) | \
|
||||
PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2;
|
||||
*pPORTH_FER |= PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8;
|
||||
# else
|
||||
*pPORTH_FER |= PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15;
|
||||
# endif
|
||||
#else
|
||||
/* grab MII & RMII pins */
|
||||
# if defined(__ADSPBF51x__)
|
||||
*pPORTF_MUX = (*pPORTF_MUX & \
|
||||
~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
|
||||
PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
|
||||
*pPORTF_FER |= PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
|
||||
*pPORTG_FER |= PG0 | PG1 | PG2;
|
||||
# elif defined(__ADSPBF52x__)
|
||||
*pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
|
||||
*pPORTG_FER |= PG14 | PG15;
|
||||
*pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2;
|
||||
*pPORTH_FER = -1; /* all pins */
|
||||
# else
|
||||
*pPORTH_FER = -1; /* all pins */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Odd word alignment for Receive Frame DMA word */
|
||||
/* Configure checksum support and rcve frame word alignment */
|
||||
*pEMAC_SYSCTL = RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(2500000));
|
||||
/* auto negotiation on */
|
||||
/* full duplex */
|
||||
/* 100 Mbps */
|
||||
phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET;
|
||||
WrPHYReg(PHYADDR, PHY_MODECTL, phydat);
|
||||
do {
|
||||
udelay(1000);
|
||||
phydat = RdPHYReg(PHYADDR, PHY_MODESTAT);
|
||||
if (count > 3000) {
|
||||
printf
|
||||
("Link is down, please check your network connection\n");
|
||||
return -1;
|
||||
}
|
||||
count++;
|
||||
} while (!(phydat & 0x0004));
|
||||
|
||||
phydat = RdPHYReg(PHYADDR, PHY_ANLPAR);
|
||||
|
||||
if ((phydat & 0x0100) || (phydat & 0x0040))
|
||||
*opmode = FDMODE;
|
||||
else
|
||||
*opmode = 0;
|
||||
|
||||
*pEMAC_MMC_CTL = RSTC | CROLL;
|
||||
|
||||
/* Initialize the TX DMA channel registers */
|
||||
*pDMA2_X_COUNT = 0;
|
||||
*pDMA2_X_MODIFY = 4;
|
||||
*pDMA2_Y_COUNT = 0;
|
||||
*pDMA2_Y_MODIFY = 0;
|
||||
|
||||
/* Initialize the RX DMA channel registers */
|
||||
*pDMA1_X_COUNT = 0;
|
||||
*pDMA1_X_MODIFY = 4;
|
||||
*pDMA1_Y_COUNT = 0;
|
||||
*pDMA1_Y_MODIFY = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADI_ETHER_BUFFER *SetupRxBuffer(int no)
|
||||
{
|
||||
ADI_ETHER_FRAME_BUFFER *frmbuf;
|
||||
|
|
|
@ -10,28 +10,8 @@
|
|||
#define __BFIN_MAC_H__
|
||||
|
||||
#define PHYADDR 0x01
|
||||
#define NO_PHY_REGS 0x20
|
||||
|
||||
#define DEFAULT_PHY_PHYID1 0x0007
|
||||
#define DEFAULT_PHY_PHYID2 0xC0A3
|
||||
#define PHY_MODECTL 0x00
|
||||
#define PHY_MODESTAT 0x01
|
||||
#define PHY_PHYID1 0x02
|
||||
#define PHY_PHYID2 0x03
|
||||
#define PHY_ANAR 0x04
|
||||
#define PHY_ANLPAR 0x05
|
||||
#define PHY_ANER 0x06
|
||||
|
||||
#define PHY_RESET 0x8000
|
||||
#define PHY_ANEG_EN 0x1000
|
||||
#define PHY_DUPLEX 0x0100
|
||||
#define PHY_SPD_SET 0x2000
|
||||
|
||||
#define RECV_BUFSIZE (0x614)
|
||||
|
||||
typedef volatile u32 reg32;
|
||||
typedef volatile u16 reg16;
|
||||
|
||||
typedef struct ADI_DMA_CONFIG_REG {
|
||||
u16 b_DMA_EN:1; /* 0 Enabled */
|
||||
u16 b_WNR:1; /* 1 Direction */
|
||||
|
@ -79,11 +59,6 @@ static void bfin_EMAC_halt(struct eth_device *dev);
|
|||
static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, int length);
|
||||
static int bfin_EMAC_recv(struct eth_device *dev);
|
||||
|
||||
static void PollMdcDone(void);
|
||||
static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data);
|
||||
static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr);
|
||||
static int SetupSystemRegs(int *opmode);
|
||||
|
||||
static void bfin_EMAC_setup_addr(bd_t *bd);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue