
On Tuesday, August 30, 2011 02:05:18 PM Michal Simek wrote:
LL Temac driver can be used by microblaze, xilinx ppc405/440 in sdma and fifo mode. DCR or XPS bus can be used.
The driver uses and requires PHYLIB.
Signed-off-by: Michal Simek monstr@monstr.eu
v2: Remove helper function for access to temac Remove SDMA/FIFO/DCR macros and configure it in board Setup mac by write_hwaddr
drivers/net/Makefile | 1 + drivers/net/xilinx_ll_temac.c | 665 +++++++++++++++++++++++++++++++++++++++++ include/netdev.h | 2 + 3 files changed, 668 insertions(+), 0 deletions(-) create mode 100644 drivers/net/xilinx_ll_temac.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 819b197..4541eaf 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -84,6 +84,7 @@ COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o +COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
COBJS := $(sort $(COBJS-y)) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c new file mode 100644 index 0000000..878cdf2 --- /dev/null +++ b/drivers/net/xilinx_ll_temac.c @@ -0,0 +1,665 @@ +/*
- Xilinx xps_ll_temac ethernet driver for u-boot
- Copyright (C) 2008 - 2011 Michal Simek monstr@monstr.eu
- Copyright (C) 2008 - 2011 PetaLogix
- Based on Yoshio Kashiwagi kashiwagi@co-nss.co.jp driver
- Copyright (C) 2008 Nissin Systems Co.,Ltd.
- March 2008 created
- 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 <config.h> +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <phy.h> +#include <miiphy.h>
+#undef ETH_HALTING
+#define XTE_EMMC_LINKSPEED_MASK 0xC0000000 /* Link speed */ +/* XTE_EMCFG_LINKSPD_MASK */ +#define XTE_EMMC_LINKSPD_10 0x00000000 /* for 10 Mbit */ +#define XTE_EMMC_LINKSPD_100 0x40000000 /* for 100 Mbit */ +#define XTE_EMMC_LINKSPD_1000 0x80000000 /* forr 1000 Mbit */
Hi,
ok, this is the usual stuff -- use (1 << n) and struct temac_regs {...};
+#define XTE_RSE_MIIM_RR_MASK 0x0002 +#define XTE_RSE_MIIM_WR_MASK 0x0004 +#define XTE_RSE_CFG_RR_MASK 0x0020 +#define XTE_RSE_CFG_WR_MASK 0x0040
+/* XPS_LL_TEMAC indirect registers offset definition */ +#define RCW1 0x240 +#define TC 0x280 +#define EMMC 0x300 +#define MC 0x340 +#define UAW0 0x380 +#define UAW1 0x384 +#define AFM 0x390 +#define MIIMWD 0x3b0 +#define MIIMAI 0x3b4
+#define CNTLREG_WRITE_ENABLE_MASK 0x8000
+#define MDIO_ENABLE_MASK 0x40 +#define MDIO_CLOCK_DIV_100MHz 0x28
+/* XPS_LL_TEMAC SDMA registers definition */ +# define TX_CURDESC_PTR 0x03 +# define TX_TAILDESC_PTR 0x04 +# define TX_CHNL_CTRL 0x05 +# define TX_IRQ_REG 0x06 +# define TX_CHNL_STS 0x07 +# define RX_NXTDESC_PTR 0x08 +# define RX_CURDESC_PTR 0x0b +# define RX_TAILDESC_PTR 0x0c +# define RX_CHNL_CTRL 0x0d +# define RX_IRQ_REG 0x0e +# define RX_CHNL_STS 0x0f
+# define DMA_CONTROL_REG 0x10
+/* CDMAC descriptor status bit definitions */ +# define BDSTAT_STOP_ON_END_MASK 0x20 +# define BDSTAT_COMPLETED_MASK 0x10 +# define BDSTAT_SOP_MASK 0x08 +# define BDSTAT_EOP_MASK 0x04
+# define CHNL_STS_ERROR_MASK 0x80
+/* All interrupt enable bits */ +#define XLLDMA_CR_IRQ_ALL_EN_MASK 0x00000087 +/* All interrupt bits */ +#define XLLDMA_IRQ_ALL_MASK 0x0000001F +/* Disable error when 2 or 4 bit coalesce counter overflows */ +#define XLLDMA_DMACR_RX_OVERFLOW_ERR_DIS_MASK 0x00000010 +/* Disable error when 2 or 4 bit coalesce counter overflows */ +#define XLLDMA_DMACR_TX_OVERFLOW_ERR_DIS_MASK 0x00000008 +/* Enable use of tail pointer register */ +#define XLLDMA_DMACR_TAIL_PTR_EN_MASK 0x00000004
+#define SDMA_BIT 1 +#define DCR_BIT 2
+#define DMAALIGN 32
+/* SDMA Buffer Descriptor */ +struct cdmac_bd_t {
- struct cdmac_bd_t *next_p;
- unsigned char *phys_buf_p;
- unsigned long buf_len;
- unsigned char stat;
- unsigned char app1_1;
- unsigned short app1_2;
- unsigned long app2;
- unsigned long app3;
- unsigned long app4;
- unsigned long app5;
maybe app[4] ?
+};
+static struct cdmac_bd_t tx_bd __attribute((aligned(DMAALIGN))); +static struct cdmac_bd_t rx_bd __attribute((aligned(DMAALIGN)));
+struct ll_fifo_s {
- int isr; /* Interrupt Status Register 0x0 */
- int ier; /* Interrupt Enable Register 0x4 */
- int tdfr; /* Transmit data FIFO reset 0x8 */
- int tdfv; /* Transmit data FIFO Vacancy 0xC */
- int tdfd; /* Transmit data FIFO 32bit wide data write port 0x10 */
- int tlf; /* Write Transmit Length FIFO 0x14 */
- int rdfr; /* Read Receive data FIFO reset 0x18 */
- int rdfo; /* Receive data FIFO Occupancy 0x1C */
- int rdfd; /* Read Receive data FIFO 32bit wide data read port 0x20 */
- int rlf; /* Read Receive Length FIFO 0x24 */
- int llr; /* Read LocalLink reset 0x28 */
+};
+static unsigned char tx_buffer[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN))); +static unsigned char rx_buffer[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN))); + +struct temac_reg {
- unsigned long msw; /* Hard TEMAC MSW Data Register */
- unsigned long lsw; /* Hard TEMAC LSW Data Register */
- unsigned long ctl; /* Hard TEMAC Control Register */
- unsigned long rdy; /* Hard TEMAC Ready Status */
+};
+struct ll_priv {
- unsigned int ctrl;
- struct temac_reg *regs;
- unsigned int mode;
- int phyaddr;
- struct phy_device *phydev;
- struct mii_dev *bus;
+};
+static void mtdcr_local(u32 reg, u32 val) +{ +#if defined(CONFIG_PPC)
- mtdcr(0x00, reg);
- mtdcr(0x01, val);
+#endif
What are these magic values with no description ?
+}
+static u32 mfdcr_local(u32 reg) +{
- u32 val = 0;
+#if defined(CONFIG_PPC)
- mtdcr(0x00, reg);
- val = mfdcr(0x01);
+#endif
dtto
- return val;
+}
+static void sdma_out_be32(struct ll_priv *priv, u32 offset, u32 val) +{
- if (priv->mode & DCR_BIT)
mtdcr_local(priv->ctrl + offset, val);
- else
out_be32((u32 *)(priv->ctrl + offset * 4), val);
If priv->ctrl was well defined structure, you won't need this cast, offset etc. Besides I see you have it defined as unsigned int ... make it u32 if you want to define registers that way. Still, struct is way to go.
+}
+static u32 sdma_in_be32(struct ll_priv *priv, u32 offset) +{
- if (priv->mode & DCR_BIT)
return mfdcr_local(priv->ctrl + offset);
- return in_be32((u32 *)(priv->ctrl + offset * 4));
DITTO, besides, in the previous code, you only do out_be32() in else branch, here you do it unconditionally. Maybe you can make them look similar.
+}
+#if defined(DEBUG) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +/* undirect hostif write to ll_temac */ +static void xps_ll_temac_hostif_set(struct eth_device *dev, int emac,
int phy_addr, int reg_addr, int phy_data)
+{
- struct ll_priv *priv = dev->priv;
- volatile struct temac_reg *regs = priv->regs;
- regs->lsw = phy_data;
- regs->ctl = CNTLREG_WRITE_ENABLE_MASK | MIIMWD;
- regs->lsw = (phy_addr << 5) | reg_addr;
- regs->ctl = CNTLREG_WRITE_ENABLE_MASK | MIIMAI | (emac << 10);
writel() or out_be32()
- while (!(regs->rdy & XTE_RSE_MIIM_WR_MASK))
;
No endless loops
+} +#endif
+/* undirect hostif read from ll_temac */ +static unsigned int xps_ll_temac_hostif_get(struct eth_device *dev,
int emac, int phy_addr, int reg_addr)
+{
- struct ll_priv *priv = dev->priv;
- volatile struct temac_reg *regs = priv->regs;
- regs->lsw = (phy_addr << 5) | reg_addr;
- regs->ctl = MIIMAI | (emac << 10);
writel() or out_be32(), please fix globally.
- while (!(regs->rdy & XTE_RSE_MIIM_RR_MASK))
;
no endless loops, please fix globally
- return regs->lsw;
return readl() I guess ...
+}
+/* undirect write to ll_temac */ +static void xps_ll_temac_indirect_set(struct eth_device *dev,
int emac, int reg_offset, int reg_data)
+{
- struct ll_priv *priv = dev->priv;
- volatile struct temac_reg *regs = priv->regs;
No volatiles please.
- regs->lsw = reg_data;
- regs->ctl = CNTLREG_WRITE_ENABLE_MASK | (emac << 10) | reg_offset;
- while (!(regs->rdy & XTE_RSE_CFG_WR_MASK))
;
+}
+/* undirect read from ll_temac */ +static int xps_ll_temac_indirect_get(struct eth_device *dev,
int emac, int reg_offset)
+{
- struct ll_priv *priv = dev->priv;
- volatile struct temac_reg *regs = priv->regs;
- regs->ctl = (emac << 10) | reg_offset;
- while (!(regs->rdy & XTE_RSE_CFG_RR_MASK))
;
- return regs->lsw;
+}
+#ifdef DEBUG +/* read from phy */ +static void read_phy_reg(struct eth_device *dev, int phy_addr) +{
- int j, result;
- debug("phy%d ", phy_addr);
- for (j = 0; j < 32; j++) {
result = xps_ll_temac_hostif_get(dev, 0, phy_addr, j);
debug("%d: 0x%x ", j, result);
- }
- debug("\n");
+} +#endif
+/* setting ll_temac and phy to proper setting */ +static int xps_ll_temac_phy_ctrl(struct eth_device *dev) +{ +#ifdef CONFIG_PHYLIB
- int i;
- unsigned int temp, speed;
- struct ll_priv *priv = dev->priv;
- struct phy_device *phydev;
- u32 supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full;
- if (priv->phyaddr == -1) {
for (i = 31; i >= 0; i--) {
temp = xps_ll_temac_hostif_get(dev, 0, i, 1);
if ((temp & 0x0ffff) != 0x0ffff) {
debug("phy %x result %x\n", i, temp);
priv->phyaddr = i;
break;
}
}
- }
- /* interface - look at tsec */
- phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0);
- phydev->supported &= supported;
- phydev->advertising = phydev->supported;
- priv->phydev = phydev;
- phy_config(phydev);
- phy_startup(phydev);
- switch (phydev->speed) {
- case 1000:
speed = XTE_EMMC_LINKSPD_1000;
break;
- case 100:
speed = XTE_EMMC_LINKSPD_100;
break;
- case 10:
speed = XTE_EMMC_LINKSPD_10;
break;
- default:
return 0;
- }
- temp = xps_ll_temac_indirect_get(dev, 0, EMMC) &
(~XTE_EMMC_LINKSPEED_MASK);
Do you need those parenthesis ? Maybe you can divide this into ...
temp = xps_ll...(); temp &= ~XTE...; temp |= speed; xps_ll...();
Might be a bit more readable.
- temp |= speed;
- xps_ll_temac_indirect_set(dev, 0, EMMC, temp);
- return 1;
+#else
- puts("Enable PHYLIB support!\n");
- return 0;
+#endif
Please move this #ifdef CONFIG_PHYLIB at the begining of the file and emit a compile-time warning.
+}
+static inline int xps_ll_temac_dma_error(struct eth_device *dev) +{
- int err;
- struct ll_priv *priv = dev->priv;
- /* Check for TX and RX channel errrors. */
- err = sdma_in_be32(priv, TX_CHNL_STS) & CHNL_STS_ERROR_MASK;
- err |= sdma_in_be32(priv, RX_CHNL_STS) & CHNL_STS_ERROR_MASK;
- return err;
+}
+static void xps_ll_temac_reset_dma(struct eth_device *dev) +{
- u32 r;
- struct ll_priv *priv = dev->priv;
- /* Soft reset the DMA. */
- sdma_out_be32(priv, DMA_CONTROL_REG, 0x00000001);
- while (sdma_in_be32(priv, DMA_CONTROL_REG) & 1)
;
Ok, maybe #define SDMA_RESET 0x1 won't hurt here.
- /* Now clear the interrupts. */
- r = sdma_in_be32(priv, TX_CHNL_CTRL);
- r &= ~XLLDMA_CR_IRQ_ALL_EN_MASK;
- sdma_out_be32(priv, TX_CHNL_CTRL, r);
- r = sdma_in_be32(priv, RX_CHNL_CTRL);
- r &= ~XLLDMA_CR_IRQ_ALL_EN_MASK;
- sdma_out_be32(priv, RX_CHNL_CTRL, r);
- /* Now ACK pending IRQs. */
- sdma_out_be32(priv, TX_IRQ_REG, XLLDMA_IRQ_ALL_MASK);
- sdma_out_be32(priv, RX_IRQ_REG, XLLDMA_IRQ_ALL_MASK);
- /* Set tail-ptr mode, disable errors for both channels. */
- sdma_out_be32(priv, DMA_CONTROL_REG,
XLLDMA_DMACR_TAIL_PTR_EN_MASK |
XLLDMA_DMACR_RX_OVERFLOW_ERR_DIS_MASK |
XLLDMA_DMACR_TX_OVERFLOW_ERR_DIS_MASK);
+}
+/* bd init */ +static void xps_ll_temac_bd_init(struct eth_device *dev) +{
- struct ll_priv *priv = dev->priv;
- memset((void *)&tx_bd, 0, sizeof(tx_bd));
- memset((void *)&rx_bd, 0, sizeof(rx_bd));
Do you need the cast?
- rx_bd.phys_buf_p = &rx_buffer[0];
rx_buffer would be sufficient here.
- rx_bd.next_p = &rx_bd;
- rx_bd.buf_len = PKTSIZE_ALIGN;
- flush_cache((u32)&rx_bd, sizeof(tx_bd));
- flush_cache((u32)rx_bd.phys_buf_p, PKTSIZE_ALIGN);
- sdma_out_be32(priv, RX_CURDESC_PTR, (u32)&rx_bd);
- sdma_out_be32(priv, RX_TAILDESC_PTR, (u32)&rx_bd);
- sdma_out_be32(priv, RX_NXTDESC_PTR, (u32)&rx_bd); /* setup first fd */
- tx_bd.phys_buf_p = &tx_buffer[0];
- tx_bd.next_p = &tx_bd;
- flush_cache((u32)&tx_bd, sizeof(tx_bd));
- sdma_out_be32(priv, TX_CURDESC_PTR, (u32)&tx_bd);
+}
+static int ll_temac_send_sdma(struct eth_device *dev,
volatile void *buffer, int length)
+{
- struct ll_priv *priv = dev->priv;
- if (xps_ll_temac_dma_error(dev)) {
xps_ll_temac_reset_dma(dev);
xps_ll_temac_bd_init(dev);
- }
- memcpy(tx_buffer, (void *)buffer, length);
- flush_cache((u32)tx_buffer, length);
- tx_bd.stat = BDSTAT_SOP_MASK | BDSTAT_EOP_MASK |
BDSTAT_STOP_ON_END_MASK;
- tx_bd.buf_len = length;
- flush_cache((u32)&tx_bd, sizeof(tx_bd));
- sdma_out_be32(priv, TX_CURDESC_PTR, (u32)&tx_bd);
- sdma_out_be32(priv, TX_TAILDESC_PTR, (u32)&tx_bd); /* DMA start */
- do {
flush_cache((u32)&tx_bd, sizeof(tx_bd));
- } while (!(((volatile int)tx_bd.stat) & BDSTAT_COMPLETED_MASK));
Whoa ... volatile int is really dangerous. And please add timeout.
- return 0;
+}
+static int ll_temac_recv_sdma(struct eth_device *dev) +{
- int length;
- struct ll_priv *priv = dev->priv;
- if (xps_ll_temac_dma_error(dev)) {
xps_ll_temac_reset_dma(dev);
xps_ll_temac_bd_init(dev);
- }
- flush_cache((u32)&rx_bd, sizeof(rx_bd));
- if (!(rx_bd.stat & BDSTAT_COMPLETED_MASK))
return 0;
- /* Read out the packet info and start the DMA
onto the second buffer to enable the ethernet rx
path to run in parallel with sw processing
packets. */
- length = rx_bd.app5 & 0x3FFF;
0x3fff should be explained here.
- if (length > 0)
NetReceive(rx_bd.phys_buf_p, length);
- /* flip the buffer and re-enable the DMA. */
- flush_cache((u32)rx_bd.phys_buf_p, length);
- rx_bd.buf_len = PKTSIZE_ALIGN;
- rx_bd.stat = 0;
- rx_bd.app5 = 0;
- flush_cache((u32)&rx_bd, sizeof(rx_bd));
- sdma_out_be32(priv, RX_TAILDESC_PTR, (u32)&rx_bd);
- return length;
+}
+#ifdef DEBUG +static void debugll(struct eth_device *dev, int count) +{
- struct ll_priv *priv = dev->priv;
- struct ll_fifo_s *ll_fifo = (void *)priv->ctrl;
- printf("%d fifo isr 0x%08x, fifo_ier 0x%08x, fifo_rdfr 0x%08x, "
"fifo_rdfo 0x%08x fifo_rlr 0x%08x\n", count, ll_fifo->isr,
ll_fifo->ier, ll_fifo->rdfr, ll_fifo->rdfo, ll_fifo->rlf);
+} +#endif
+static int ll_temac_send_fifo(struct eth_device *dev,
volatile void *buffer, int length)
+{
- struct ll_priv *priv = dev->priv;
- struct ll_fifo_s *ll_fifo = (void *)priv->ctrl;
- u32 *buf = (u32 *)buffer;
- u32 len, i, val;
- len = (length / 4) + 1;
Do you need the len at all ?
for (i = 0; i < length; i +=4 ) writel(*buf++, ll_fifo->tdfd);
- for (i = 0; i < len; i++) {
val = *buf++;
ll_fifo->tdfd = val;
- }
- ll_fifo->tlf = length;
- return 0;
+}
+static int ll_temac_recv_fifo(struct eth_device *dev) +{
- struct ll_priv *priv = dev->priv;
- struct ll_fifo_s *ll_fifo = (void *)priv->ctrl;
- u32 len = 0;
- u32 len2, i, val;
- u32 *buf = (u32 *)&rx_buffer;
- if (ll_fifo->isr & 0x04000000) {
Another magic value, please fix globally.
ll_fifo->isr = 0xffffffff; /* reset isr */
/* while (ll_fifo->isr); */
len = ll_fifo->rlf & 0x7FF;
len2 = (len / 4) + 1;
for (i = 0; i < len2; i++) {
val = ll_fifo->rdfd;
*buf++ = val ;
}
+#ifdef DEBUG
debugll(dev, 1);
+#endif
NetReceive((uchar *)&rx_buffer, len);
- }
- return len;
+}
+/* setup mac addr */ +static int ll_temac_addr_setup(struct eth_device *dev) +{
- int val;
- /* set up unicast MAC address filter */
- val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
(dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
- xps_ll_temac_indirect_set(dev, 0, UAW0, val);
- val = (dev->enetaddr[5] << 8) | dev->enetaddr[4] ;
- xps_ll_temac_indirect_set(dev, 0, UAW1, val);
- return 0;
+}
+static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{
- struct ll_priv *priv = dev->priv;
- struct ll_fifo_s *ll_fifo = (void *)priv->ctrl;
- if (priv->mode & SDMA_BIT) {
xps_ll_temac_reset_dma(dev);
xps_ll_temac_bd_init(dev);
- } else {
ll_fifo->tdfr = 0x000000a5; /* set fifo length */
ll_fifo->rdfr = 0x000000a5;
/* ll_fifo->isr = 0x0; */
/* ll_fifo->ier = 0x0; */
Why do you have this dead code here?
- }
- xps_ll_temac_indirect_set(dev, 0, MC,
MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
- /* Promiscuous mode disable */
- xps_ll_temac_indirect_set(dev, 0, AFM, 0x00000000);
- /* Enable Receiver */
- xps_ll_temac_indirect_set(dev, 0, RCW1, 0x10000000);
- /* Enable Transmitter */
- xps_ll_temac_indirect_set(dev, 0, TC, 0x10000000);
Magic values.
- return 0;
+}
+/* halt device */ +static void ll_temac_halt(struct eth_device *dev) +{ +#ifdef ETH_HALTING
- struct ll_priv *priv = dev->priv;
- /* Disable Receiver */
- xps_ll_temac_indirect_set(dev, 0, RCW1, 0x00000000);
- /* Disable Transmitter */
Magic.
- xps_ll_temac_indirect_set(dev, 0, TC, 0x00000000);
- if (priv->mode & SDMA_BIT) {
sdma_out_be32(priv->ctrl, DMA_CONTROL_REG, 0x00000001);
while (sdma_in_be32(priv->ctrl, DMA_CONTROL_REG) & 1)
;
- }
- /* reset fifos */
Dead comment?
+#endif +}
+static int ll_temac_init(struct eth_device *dev, bd_t *bis) +{
- struct ll_priv *priv = dev->priv;
+#if DEBUG
- int i;
+#endif
- xps_ll_temac_init(dev, bis);
- printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, 0, dev->iobase);
+#if DEBUG
- for (i = 0; i < 32; i++)
read_phy_reg(dev, i);
+#endif
- if (!xps_ll_temac_phy_ctrl(dev)) {
ll_temac_halt(dev);
return -1;
- }
- return 0;
+}
+static int ll_temac_miiphy_read(const char *devname, uchar addr,
uchar reg, ushort *val)
+{
- struct eth_device *dev = eth_get_dev();
- *val = xps_ll_temac_hostif_get(dev, 0, addr, reg); /* emac = 0 */
- debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val);
- return 0;
+}
+static int ll_temac_miiphy_write(const char *devname, uchar addr,
uchar reg, ushort val)
+{
- struct eth_device *dev = eth_get_dev();
- debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val);
- xps_ll_temac_hostif_set(dev, 0, addr, reg, val);
- return 0;
+}
+static int ll_temac_bus_reset(struct mii_dev *bus) +{
- debug("Just bus reset\n");
- return 0;
+}
+/* mode bits: 0bit - fifo(0)/sdma(1):SDMA_BIT, 1bit - no dcr(0)/dcr(1):DCR_BIT + * ctrl - control address for file/sdma */ +int xilinx_ll_temac_initialize(bd_t *bis, unsigned long base_addr,
int mode, int ctrl)
+{
- struct eth_device *dev;
- struct ll_priv *priv;
- dev = calloc(1, sizeof(*dev));
- if (dev == NULL)
return -1;
- dev->priv = calloc(1, sizeof(struct ll_priv));
- if (dev->priv == NULL) {
free(dev);
return -1;
- }
- priv = dev->priv;
- sprintf(dev->name, "Xlltem.%lx", base_addr);
- dev->iobase = base_addr;
- priv->regs = (void *) (base_addr + 0x20);
Here you'd just load the struct :)
- priv->ctrl = ctrl;
- priv->mode = mode;
+#ifdef CONFIG_PHY_ADDR
- priv->phyaddr = CONFIG_PHY_ADDR;
+#else
- priv->phyaddr = -1;
+#endif
- dev->init = ll_temac_init;
- dev->halt = ll_temac_halt;
- dev->write_hwaddr = ll_temac_addr_setup;
- if (priv->mode & SDMA_BIT) {
dev->send = ll_temac_send_sdma;
dev->recv = ll_temac_recv_sdma;
- } else {
dev->send = ll_temac_send_fifo;
dev->recv = ll_temac_recv_fifo;
- }
- eth_register(dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) + miiphy_register(dev->name, ll_temac_miiphy_read, ll_temac_miiphy_write); + priv->bus = miiphy_get_dev_by_name(dev->name);
- priv->bus->reset = ll_temac_bus_reset;
+#endif
- return 1;
+} diff --git a/include/netdev.h b/include/netdev.h index 26ce13d..cebae3b 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -92,6 +92,8 @@ int uec_standard_init(bd_t *bis); int uli526x_initialize(bd_t *bis); int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr, int txpp, int rxpp); +int xilinx_ll_temac_initialize(bd_t *bis, unsigned long base_addr,
int mode, int ctrl);
int sh_eth_initialize(bd_t *bis); int dm9000_initialize(bd_t *bis); int fecmxc_initialize(bd_t *bis);
The driver has some way to go, but it's mostly coding style. One or two more rounds and it's ready.
Cheers!