From: Mike Frysinger Date: Mon, 25 Feb 2008 04:58:13 +0000 (-0500) Subject: net/Blackfin: move on-chip MAC driver into drivers/net/ X-Git-Tag: v1.3.3-rc1~183 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=395bce4f59a507a60a475f7ee46bed47de9482df;p=u-boot net/Blackfin: move on-chip MAC driver into drivers/net/ The Blackfin on-chip MAC driver was being managed in the BF537-STAMP board directory, but it is not board specific, so relocate it to the drivers dir so that other Blackfin ports can utilize it. Signed-off-by: Mike Frysinger --- diff --git a/board/bf537-stamp/Makefile b/board/bf537-stamp/Makefile index cdffc333eb..5d22393371 100644 --- a/board/bf537-stamp/Makefile +++ b/board/bf537-stamp/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS := $(BOARD).o ether_bf537.o post-memory.o stm_m25p64.o cmd_bf537led.o nand.o +COBJS := $(BOARD).o post-memory.o stm_m25p64.o cmd_bf537led.o nand.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/bf537-stamp/ether_bf537.c b/board/bf537-stamp/ether_bf537.c deleted file mode 100644 index 6c514c6609..0000000000 --- a/board/bf537-stamp/ether_bf537.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * ADI Blackfin 537 MAC Ethernet - * - * Copyright (c) 2005 Analog Device, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * 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. - * - * This program is distributed in the hope that 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 - */ - -#include -#include -#include -#include -#include -#include -#include "ether_bf537.h" - -#include -#include -#include - -#ifdef CONFIG_POST -#include -#endif - -#undef DEBUG_ETHERNET - -#ifdef DEBUG_ETHERNET -#define DEBUGF(fmt,args...) printf(fmt,##args) -#else -#define DEBUGF(fmt,args...) -#endif - -#if defined(CONFIG_CMD_NET) - -#define RXBUF_BASE_ADDR 0xFF900000 -#define TXBUF_BASE_ADDR 0xFF800000 -#define TX_BUF_CNT 1 - -#define TOUT_LOOP 1000000 - -ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT]; -ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX]; -static u16 txIdx; /* index of the current RX buffer */ -static u16 rxIdx; /* index of the current TX buffer */ - -u8 SrcAddr[6]; -u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */ - -/* DMAx_CONFIG values at DMA Restart */ -const ADI_DMA_CONFIG_REG rxdmacfg = { 1, 1, 2, 0, 0, 0, 0, 5, 7 }; - -#if 0 - rxdmacfg.b_DMA_EN = 1; /* enabled */ - rxdmacfg.b_WNR = 1; /* write to memory */ - rxdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */ - rxdmacfg.b_DMA2D = 0; /* N/A */ - rxdmacfg.b_RESTART= 0; /* N/A */ - rxdmacfg.b_DI_SEL = 0; /* N/A */ - rxdmacfg.b_DI_EN = 0; /* no interrupt */ - rxdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */ - rxdmacfg.b_FLOW = 7; /* large desc flow */ -#endif - -const ADI_DMA_CONFIG_REG txdmacfg = { 1, 0, 2, 0, 0, 0, 0, 5, 7 }; - -#if 0 - txdmacfg.b_DMA_EN = 1; /* enabled */ - txdmacfg.b_WNR = 0; /* read from memory */ - txdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */ - txdmacfg.b_DMA2D = 0; /* N/A */ - txdmacfg.b_RESTART= 0; /* N/A */ - txdmacfg.b_DI_SEL = 0; /* N/A */ - txdmacfg.b_DI_EN = 0; /* no interrupt */ - txdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */ - txdmacfg.b_FLOW = 7; /* large desc flow */ -#endif - -ADI_ETHER_BUFFER *SetupRxBuffer(int no); -ADI_ETHER_BUFFER *SetupTxBuffer(int no); - -static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd); -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); - -int bfin_EMAC_initialize(bd_t * bis) -{ - struct eth_device *dev; - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (dev == NULL) - hang(); - - memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "BF537 ETHERNET"); - - dev->iobase = 0; - dev->priv = 0; - dev->init = bfin_EMAC_init; - dev->halt = bfin_EMAC_halt; - dev->send = bfin_EMAC_send; - dev->recv = bfin_EMAC_recv; - - eth_register(dev); - - return 1; -} - -static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, - int length) -{ - int i; - int result = 0; - unsigned int *buf; - buf = (unsigned int *)packet; - - if (length <= 0) { - printf("Ethernet: bad packet size: %d\n", length); - goto out; - } - - if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) { - printf("Ethernet: tx DMA error\n"); - goto out; - } - - for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) { - if (i > TOUT_LOOP) { - puts("Ethernet: tx time out\n"); - goto out; - } - } - txbuf[txIdx]->FrmData->NoBytes = length; - memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length); - txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData; - *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0]; - *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg); - *pEMAC_OPMODE |= TE; - - for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) { - if (i > TOUT_LOOP) { - puts("Ethernet: tx error\n"); - goto out; - } - } - result = txbuf[txIdx]->StatusWord; - txbuf[txIdx]->StatusWord = 0; - if ((txIdx + 1) >= TX_BUF_CNT) - txIdx = 0; - else - txIdx++; - out: - DEBUGF("BFIN EMAC send: length = %d\n", length); - return result; -} - -static int bfin_EMAC_recv(struct eth_device *dev) -{ - int length = 0; - - for (;;) { - if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) { - length = -1; - break; - } - if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) { - printf("Ethernet: rx dma overrun\n"); - break; - } - if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) { - printf("Ethernet: rx error\n"); - break; - } - length = rxbuf[rxIdx]->StatusWord & 0x000007FF; - if (length <= 4) { - printf("Ethernet: bad frame\n"); - break; - } - NetRxPackets[rxIdx] = - (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest); - NetReceive(NetRxPackets[rxIdx], length - 4); - *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR; - rxbuf[rxIdx]->StatusWord = 0x00000000; - if ((rxIdx + 1) >= PKTBUFSRX) - rxIdx = 0; - else - rxIdx++; - } - - return length; -} - -/************************************************************** - * - * Ethernet Initialization Routine - * - *************************************************************/ - -static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd) -{ - u32 opmode; - int dat; - int i; - DEBUGF("Eth_init: ......\n"); - - txIdx = 0; - rxIdx = 0; - -/* Initialize System Register */ - if (SetupSystemRegs(&dat) < 0) - return -1; - -/* Initialize EMAC address */ - SetupMacAddr(SrcAddr); - -/* Initialize TX and RX buffer */ - for (i = 0; i < PKTBUFSRX; i++) { - rxbuf[i] = SetupRxBuffer(i); - if (i > 0) { - rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = - &(rxbuf[i]->Dma[0]); - if (i == (PKTBUFSRX - 1)) - rxbuf[i]->Dma[1].NEXT_DESC_PTR = - &(rxbuf[0]->Dma[0]); - } - } - for (i = 0; i < TX_BUF_CNT; i++) { - txbuf[i] = SetupTxBuffer(i); - if (i > 0) { - txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = - &(txbuf[i]->Dma[0]); - if (i == (TX_BUF_CNT - 1)) - txbuf[i]->Dma[1].NEXT_DESC_PTR = - &(txbuf[0]->Dma[0]); - } - } - - /* Set RX DMA */ - *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0]; - *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG); - - /* Wait MII done */ - PollMdcDone(); - - /* We enable only RX here */ - /* ASTP : Enable Automatic Pad Stripping - PR : Promiscuous Mode for test - PSF : Receive frames with total length less than 64 bytes. - FDMODE : Full Duplex Mode - LB : Internal Loopback for test - RE : Receiver Enable */ - if (dat == FDMODE) - opmode = ASTP | FDMODE | PSF; - else - opmode = ASTP | PSF; - opmode |= RE; -#ifdef CONFIG_BFIN_MAC_RMII - opmode |= TE | RMII; -#endif - /* Turn on the EMAC */ - *pEMAC_OPMODE = opmode; - return 0; -} - -static void bfin_EMAC_halt(struct eth_device *dev) -{ - DEBUGF("Eth_halt: ......\n"); - /* Turn off the EMAC */ - *pEMAC_OPMODE = 0x00000000; - /* Turn off the EMAC RX DMA */ - *pDMA1_CONFIG = 0x0000; - *pDMA2_CONFIG = 0x0000; - -} - -void SetupMacAddr(u8 * MACaddr) -{ - char *tmp, *end; - int i; - /* this depends on a little-endian machine */ - tmp = getenv("ethaddr"); - if (tmp) { - for (i = 0; i < 6; i++) { - MACaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; - if (tmp) - tmp = (*end) ? end + 1 : end; - } - -#ifndef CONFIG_NETCONSOLE - printf("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", - MACaddr[0], MACaddr[1], - MACaddr[2], MACaddr[3], MACaddr[4], MACaddr[5]); -#endif - *pEMAC_ADDRLO = MACaddr[0] | MACaddr[1] << 8 | - MACaddr[2] << 16 | MACaddr[3] << 24; - *pEMAC_ADDRHI = MACaddr[4] | MACaddr[5] << 8; - } -} - -void PollMdcDone(void) -{ - /* poll the STABUSY bit */ - while (*pEMAC_STAADD & STABUSY) ; -} - -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 * - *********************************************************************************/ -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; -} - -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); -} - -int SetupSystemRegs(int *opmode) -{ - u16 sysctl, phydat; - int count = 0; - /* Enable PHY output */ - *pVR_CTL |= CLKBUFOE; - /* MDC = 2.5 MHz */ - sysctl = SET_MDCDIV(24); - /* Odd word alignment for Receive Frame DMA word */ - /* Configure checksum support and rcve frame word alignment */ - sysctl |= RXDWA | RXCKS; - *pEMAC_SYSCTL = sysctl; - /* 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; - ADI_ETHER_BUFFER *buf; - int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ - int total_size = nobytes_buffer + RECV_BUFSIZE; - - buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size); - frmbuf = - (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size + - nobytes_buffer); - - memset(buf, 0x00, nobytes_buffer); - buf->FrmData = frmbuf; - memset(frmbuf, 0xfe, RECV_BUFSIZE); - - /* set up first desc to point to receive frame buffer */ - buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); - buf->Dma[0].START_ADDR = (u32) buf->FrmData; - buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ - buf->Dma[0].CONFIG.b_WNR = 1; /* Write to memory */ - buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ - buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ - buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ - - /* set up second desc to point to status word */ - buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); - buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum; - buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ - buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ - buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ - buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ - buf->Dma[1].CONFIG.b_NDSIZE = 5; /* must be 0 when FLOW is 0 */ - buf->Dma[1].CONFIG.b_FLOW = 7; /* stop */ - - return buf; -} - -ADI_ETHER_BUFFER *SetupTxBuffer(int no) -{ - ADI_ETHER_FRAME_BUFFER *frmbuf; - ADI_ETHER_BUFFER *buf; - int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ - int total_size = nobytes_buffer + RECV_BUFSIZE; - - buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size); - frmbuf = - (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size + - nobytes_buffer); - - memset(buf, 0x00, nobytes_buffer); - buf->FrmData = frmbuf; - memset(frmbuf, 0x00, RECV_BUFSIZE); - - /* set up first desc to point to receive frame buffer */ - buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); - buf->Dma[0].START_ADDR = (u32) buf->FrmData; - buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ - buf->Dma[0].CONFIG.b_WNR = 0; /* Read to memory */ - buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ - buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ - buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ - - /* set up second desc to point to status word */ - buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); - buf->Dma[1].START_ADDR = (u32) & buf->StatusWord; - buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ - buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ - buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ - buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ - buf->Dma[1].CONFIG.b_NDSIZE = 0; /* must be 0 when FLOW is 0 */ - buf->Dma[1].CONFIG.b_FLOW = 0; /* stop */ - - return buf; -} - -#if defined(CONFIG_POST) && defined(CFG_POST_ETHER) -int ether_post_test(int flags) -{ - uchar buf[64]; - int i, value = 0; - int length; - - printf("\n--------"); - bfin_EMAC_init(NULL, NULL); - /* construct the package */ - buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF); - buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8); - buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16); - buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24); - buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF); - buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8); - buf[12] = 0x08; /* Type: ARP */ - buf[13] = 0x06; - buf[14] = 0x00; /* Hardware type: Ethernet */ - buf[15] = 0x01; - buf[16] = 0x08; /* Protocal type: IP */ - buf[17] = 0x00; - buf[18] = 0x06; /* Hardware size */ - buf[19] = 0x04; /* Protocol size */ - buf[20] = 0x00; /* Opcode: request */ - buf[21] = 0x01; - - for (i = 0; i < 42; i++) - buf[i + 22] = i; - printf("--------Send 64 bytes......\n"); - bfin_EMAC_send(NULL, (volatile void *)buf, 64); - for (i = 0; i < 100; i++) { - udelay(10000); - if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) { - value = 1; - break; - } - } - if (value == 0) { - printf("--------EMAC can't receive any data\n"); - eth_halt(); - return -1; - } - length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4; - for (i = 0; i < length; i++) { - if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) { - printf("--------EMAC receive error data!\n"); - eth_halt(); - return -1; - } - } - printf("--------receive %d bytes, matched\n", length); - bfin_EMAC_halt(NULL); - return 0; -} -#endif -#endif diff --git a/board/bf537-stamp/ether_bf537.h b/board/bf537-stamp/ether_bf537.h deleted file mode 100644 index 22fc392ddc..0000000000 --- a/board/bf537-stamp/ether_bf537.h +++ /dev/null @@ -1,71 +0,0 @@ -#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 */ - u16 b_WDSIZE:2; /* 2:3 Transfer word size */ - u16 b_DMA2D:1; /* 4 DMA mode */ - u16 b_RESTART:1; /* 5 Retain FIFO */ - u16 b_DI_SEL:1; /* 6 Data interrupt timing select */ - u16 b_DI_EN:1; /* 7 Data interrupt enabled */ - u16 b_NDSIZE:4; /* 8:11 Flex descriptor size */ - u16 b_FLOW:3; /* 12:14Flow */ -} ADI_DMA_CONFIG_REG; - -typedef struct adi_ether_frame_buffer { - u16 NoBytes; /* the no. of following bytes */ - u8 Dest[6]; /* destination MAC address */ - u8 Srce[6]; /* source MAC address */ - u16 LTfield; /* length/type field */ - u8 Data[0]; /* payload bytes */ -} ADI_ETHER_FRAME_BUFFER; -/* 16 bytes/struct */ - -typedef struct dma_descriptor { - struct dma_descriptor *NEXT_DESC_PTR; - u32 START_ADDR; - ADI_DMA_CONFIG_REG CONFIG; -} DMA_DESCRIPTOR; -/* 10 bytes/struct in 12 bytes */ - -typedef struct adi_ether_buffer { - DMA_DESCRIPTOR Dma[2]; /* first for the frame, second for the status */ - ADI_ETHER_FRAME_BUFFER *FrmData;/* pointer to data */ - struct adi_ether_buffer *pNext; /* next buffer */ - struct adi_ether_buffer *pPrev; /* prev buffer */ - u16 IPHdrChksum; /* the IP header checksum */ - u16 IPPayloadChksum; /* the IP header and payload checksum */ - volatile u32 StatusWord; /* the frame status word */ -} ADI_ETHER_BUFFER; -/* 40 bytes/struct in 44 bytes */ - -void SetupMacAddr(u8 * MACaddr); - -void PollMdcDone(void); -void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data); -u16 RdPHYReg(u16 PHYAddr, u16 RegAddr); -void SoftResetPHY(void); -void DumpPHYRegs(void); - -int SetupSystemRegs(int *opmode); diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b9723fa78f..321bd08adb 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libnet.a COBJS-y += 3c589.o COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o +COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o COBJS-y += cs8900.o COBJS-y += dc2114x.o COBJS-y += dm9000x.o diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c new file mode 100644 index 0000000000..afe122a337 --- /dev/null +++ b/drivers/net/bfin_mac.c @@ -0,0 +1,523 @@ +/* + * Driver for Blackfin On-Chip MAC device + * + * Copyright (c) 2005-2008 Analog Device, Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "bfin_mac.h" + +#ifdef CONFIG_POST +#include +#endif + +#undef DEBUG_ETHERNET + +#ifdef DEBUG_ETHERNET +#define DEBUGF(fmt, args...) printf(fmt, ##args) +#else +#define DEBUGF(fmt, args...) +#endif + +#define RXBUF_BASE_ADDR 0xFF900000 +#define TXBUF_BASE_ADDR 0xFF800000 +#define TX_BUF_CNT 1 + +#define TOUT_LOOP 1000000 + +ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT]; +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 */ + .b_WNR = 1, /* write to memory */ + .b_WDSIZE = 2, /* wordsize is 32 bits */ + .b_DMA2D = 0, + .b_RESTART = 0, + .b_DI_SEL = 0, + .b_DI_EN = 0, /* no interrupt */ + .b_NDSIZE = 5, /* 5 half words is desc size */ + .b_FLOW = 7 /* large desc flow */ +}; + +const ADI_DMA_CONFIG_REG txdmacfg = { + .b_DMA_EN = 1, /* enabled */ + .b_WNR = 0, /* read from memory */ + .b_WDSIZE = 2, /* wordsize is 32 bits */ + .b_DMA2D = 0, + .b_RESTART = 0, + .b_DI_SEL = 0, + .b_DI_EN = 0, /* no interrupt */ + .b_NDSIZE = 5, /* 5 half words is desc size */ + .b_FLOW = 7 /* large desc flow */ +}; + +int bfin_EMAC_initialize(bd_t *bis) +{ + struct eth_device *dev; + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (dev == NULL) + hang(); + + memset(dev, 0, sizeof(*dev)); + sprintf(dev->name, "Blackfin EMAC"); + + dev->iobase = 0; + dev->priv = 0; + dev->init = bfin_EMAC_init; + dev->halt = bfin_EMAC_halt; + dev->send = bfin_EMAC_send; + dev->recv = bfin_EMAC_recv; + + eth_register(dev); + + return 1; +} + +static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, + int length) +{ + int i; + int result = 0; + unsigned int *buf; + buf = (unsigned int *)packet; + + if (length <= 0) { + printf("Ethernet: bad packet size: %d\n", length); + goto out; + } + + if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) { + printf("Ethernet: tx DMA error\n"); + goto out; + } + + for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) { + if (i > TOUT_LOOP) { + puts("Ethernet: tx time out\n"); + goto out; + } + } + txbuf[txIdx]->FrmData->NoBytes = length; + memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length); + txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData; + *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0]; + *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg); + *pEMAC_OPMODE |= TE; + + for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) { + if (i > TOUT_LOOP) { + puts("Ethernet: tx error\n"); + goto out; + } + } + result = txbuf[txIdx]->StatusWord; + txbuf[txIdx]->StatusWord = 0; + if ((txIdx + 1) >= TX_BUF_CNT) + txIdx = 0; + else + txIdx++; + out: + DEBUGF("BFIN EMAC send: length = %d\n", length); + return result; +} + +static int bfin_EMAC_recv(struct eth_device *dev) +{ + int length = 0; + + for (;;) { + if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) { + length = -1; + break; + } + if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) { + printf("Ethernet: rx dma overrun\n"); + break; + } + if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) { + printf("Ethernet: rx error\n"); + break; + } + length = rxbuf[rxIdx]->StatusWord & 0x000007FF; + if (length <= 4) { + printf("Ethernet: bad frame\n"); + break; + } + NetRxPackets[rxIdx] = + (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest); + NetReceive(NetRxPackets[rxIdx], length - 4); + *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR; + rxbuf[rxIdx]->StatusWord = 0x00000000; + if ((rxIdx + 1) >= PKTBUFSRX) + rxIdx = 0; + else + rxIdx++; + } + + return length; +} + +/************************************************************** + * + * Ethernet Initialization Routine + * + *************************************************************/ + +static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd) +{ + u32 opmode; + int dat; + int i; + DEBUGF("Eth_init: ......\n"); + + txIdx = 0; + rxIdx = 0; + +/* Initialize System Register */ + if (SetupSystemRegs(&dat) < 0) + return -1; + +/* Initialize EMAC address */ + bfin_EMAC_setup_addr(bd); + +/* Initialize TX and RX buffer */ + for (i = 0; i < PKTBUFSRX; i++) { + rxbuf[i] = SetupRxBuffer(i); + if (i > 0) { + rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = + &(rxbuf[i]->Dma[0]); + if (i == (PKTBUFSRX - 1)) + rxbuf[i]->Dma[1].NEXT_DESC_PTR = + &(rxbuf[0]->Dma[0]); + } + } + for (i = 0; i < TX_BUF_CNT; i++) { + txbuf[i] = SetupTxBuffer(i); + if (i > 0) { + txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = + &(txbuf[i]->Dma[0]); + if (i == (TX_BUF_CNT - 1)) + txbuf[i]->Dma[1].NEXT_DESC_PTR = + &(txbuf[0]->Dma[0]); + } + } + + /* Set RX DMA */ + *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0]; + *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG); + + /* Wait MII done */ + PollMdcDone(); + + /* We enable only RX here */ + /* ASTP : Enable Automatic Pad Stripping + PR : Promiscuous Mode for test + PSF : Receive frames with total length less than 64 bytes. + FDMODE : Full Duplex Mode + LB : Internal Loopback for test + RE : Receiver Enable */ + if (dat == FDMODE) + opmode = ASTP | FDMODE | PSF; + else + opmode = ASTP | PSF; + opmode |= RE; +#ifdef CONFIG_BFIN_MAC_RMII + opmode |= TE | RMII; +#endif + /* Turn on the EMAC */ + *pEMAC_OPMODE = opmode; + return 0; +} + +static void bfin_EMAC_halt(struct eth_device *dev) +{ + DEBUGF("Eth_halt: ......\n"); + /* Turn off the EMAC */ + *pEMAC_OPMODE = 0x00000000; + /* Turn off the EMAC RX DMA */ + *pDMA1_CONFIG = 0x0000; + *pDMA2_CONFIG = 0x0000; + +} + +void bfin_EMAC_setup_addr(bd_t *bd) +{ + *pEMAC_ADDRLO = + bd->bi_enetaddr[0] | + bd->bi_enetaddr[1] << 8 | + bd->bi_enetaddr[2] << 16 | + bd->bi_enetaddr[3] << 24; + *pEMAC_ADDRHI = + bd->bi_enetaddr[4] | + 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 + +static int SetupSystemRegs(int *opmode) +{ + u16 sysctl, phydat; + int count = 0; + /* Enable PHY output */ + *pVR_CTL |= CLKBUFOE; + /* Set all the pins to peripheral mode */ + +#ifndef CONFIG_BFIN_MAC_RMII + *pPORTH_FER = 0xFFFF; +#ifdef __ADSPBF52x__ + *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2; +#endif +#else +#if defined(__ADSPBF536__) || defined(__ADSPBF537__) + *pPORTH_FER = 0xC373; +#endif +#ifdef __ADSPBF52x__ + *pPORTH_FER = 0x01FF; + *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2; +#endif +#endif + /* MDC = 2.5 MHz */ + sysctl = SET_MDCDIV(24); + /* Odd word alignment for Receive Frame DMA word */ + /* Configure checksum support and rcve frame word alignment */ + sysctl |= RXDWA | RXCKS; + *pEMAC_SYSCTL = sysctl; + /* 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; + ADI_ETHER_BUFFER *buf; + int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ + int total_size = nobytes_buffer + RECV_BUFSIZE; + + buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size); + frmbuf = + (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size + + nobytes_buffer); + + memset(buf, 0x00, nobytes_buffer); + buf->FrmData = frmbuf; + memset(frmbuf, 0xfe, RECV_BUFSIZE); + + /* set up first desc to point to receive frame buffer */ + buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); + buf->Dma[0].START_ADDR = (u32) buf->FrmData; + buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[0].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ + buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ + + /* set up second desc to point to status word */ + buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); + buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum; + buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ + buf->Dma[1].CONFIG.b_NDSIZE = 5; /* must be 0 when FLOW is 0 */ + buf->Dma[1].CONFIG.b_FLOW = 7; /* stop */ + + return buf; +} + +ADI_ETHER_BUFFER *SetupTxBuffer(int no) +{ + ADI_ETHER_FRAME_BUFFER *frmbuf; + ADI_ETHER_BUFFER *buf; + int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */ + int total_size = nobytes_buffer + RECV_BUFSIZE; + + buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size); + frmbuf = + (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size + + nobytes_buffer); + + memset(buf, 0x00, nobytes_buffer); + buf->FrmData = frmbuf; + memset(frmbuf, 0x00, RECV_BUFSIZE); + + /* set up first desc to point to receive frame buffer */ + buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); + buf->Dma[0].START_ADDR = (u32) buf->FrmData; + buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[0].CONFIG.b_WNR = 0; /* Read to memory */ + buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */ + buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */ + + /* set up second desc to point to status word */ + buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); + buf->Dma[1].START_ADDR = (u32) & buf->StatusWord; + buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */ + buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */ + buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */ + buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */ + buf->Dma[1].CONFIG.b_NDSIZE = 0; /* must be 0 when FLOW is 0 */ + buf->Dma[1].CONFIG.b_FLOW = 0; /* stop */ + + return buf; +} + +#if defined(CONFIG_POST) && defined(CFG_POST_ETHER) +int ether_post_test(int flags) +{ + uchar buf[64]; + int i, value = 0; + int length; + + printf("\n--------"); + bfin_EMAC_init(NULL, NULL); + /* construct the package */ + buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF); + buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8); + buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16); + buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24); + buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF); + buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8); + buf[12] = 0x08; /* Type: ARP */ + buf[13] = 0x06; + buf[14] = 0x00; /* Hardware type: Ethernet */ + buf[15] = 0x01; + buf[16] = 0x08; /* Protocal type: IP */ + buf[17] = 0x00; + buf[18] = 0x06; /* Hardware size */ + buf[19] = 0x04; /* Protocol size */ + buf[20] = 0x00; /* Opcode: request */ + buf[21] = 0x01; + + for (i = 0; i < 42; i++) + buf[i + 22] = i; + printf("--------Send 64 bytes......\n"); + bfin_EMAC_send(NULL, (volatile void *)buf, 64); + for (i = 0; i < 100; i++) { + udelay(10000); + if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) { + value = 1; + break; + } + } + if (value == 0) { + printf("--------EMAC can't receive any data\n"); + eth_halt(); + return -1; + } + length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4; + for (i = 0; i < length; i++) { + if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) { + printf("--------EMAC receive error data!\n"); + eth_halt(); + return -1; + } + } + printf("--------receive %d bytes, matched\n", length); + bfin_EMAC_halt(NULL); + return 0; +} +#endif diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h new file mode 100644 index 0000000000..c8a94d0c9f --- /dev/null +++ b/drivers/net/bfin_mac.h @@ -0,0 +1,89 @@ +/* + * bfin_mac.h - some defines/structures for the Blackfin on-chip MAC. + * + * Copyright (c) 2005-2008 Analog Device, Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_MAC_H__ +#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 */ + u16 b_WDSIZE:2; /* 2:3 Transfer word size */ + u16 b_DMA2D:1; /* 4 DMA mode */ + u16 b_RESTART:1; /* 5 Retain FIFO */ + u16 b_DI_SEL:1; /* 6 Data interrupt timing select */ + u16 b_DI_EN:1; /* 7 Data interrupt enabled */ + u16 b_NDSIZE:4; /* 8:11 Flex descriptor size */ + u16 b_FLOW:3; /* 12:14Flow */ +} ADI_DMA_CONFIG_REG; + +typedef struct adi_ether_frame_buffer { + u16 NoBytes; /* the no. of following bytes */ + u8 Dest[6]; /* destination MAC address */ + u8 Srce[6]; /* source MAC address */ + u16 LTfield; /* length/type field */ + u8 Data[0]; /* payload bytes */ +} ADI_ETHER_FRAME_BUFFER; +/* 16 bytes/struct */ + +typedef struct dma_descriptor { + struct dma_descriptor *NEXT_DESC_PTR; + u32 START_ADDR; + ADI_DMA_CONFIG_REG CONFIG; +} DMA_DESCRIPTOR; +/* 10 bytes/struct in 12 bytes */ + +typedef struct adi_ether_buffer { + DMA_DESCRIPTOR Dma[2]; /* first for the frame, second for the status */ + ADI_ETHER_FRAME_BUFFER *FrmData;/* pointer to data */ + struct adi_ether_buffer *pNext; /* next buffer */ + struct adi_ether_buffer *pPrev; /* prev buffer */ + u16 IPHdrChksum; /* the IP header checksum */ + u16 IPPayloadChksum; /* the IP header and payload checksum */ + volatile u32 StatusWord; /* the frame status word */ +} ADI_ETHER_BUFFER; +/* 40 bytes/struct in 44 bytes */ + +static ADI_ETHER_BUFFER *SetupRxBuffer(int no); +static ADI_ETHER_BUFFER *SetupTxBuffer(int no); + +static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd); +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