Skip to contentSkip to conversation

Xilinx PowerPC XPS_LL_TEMAC driver

PATCH New Yoshio Kashiwagi 3 participants 3 messages Apr 26, 2008 – Apr 27, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Xilinx PowerPC XPS_LL_TEMAC driver

---
 drivers/net/Makefile          |    1 +
 drivers/net/xilinx_ll_temac.c |  371 ++++++++++++++++++++++++++++++++++
+++++++
 2 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/xilinx_ll_temac.c
drivers/net/Makefile +1 -0
index d5e413b..a11238b 100644
@@ -63,6 +63,7 @@ COBJS-y += uli526x.o
 COBJS-y += vsc7385.o
 COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC)) += xilinx_ll_temac.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
drivers/net/xilinx_ll_temac. renamed from drivers/net/xilinx_ll_temac.c +0 -0

c
new file mode 100644
index 0000000..2f75ebc

drivers/net/xilinx_ll_temac.c new file +11 -0
@@ -0,0 +1,371 @@
+/*
+ *
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * Author: Yoshio Kashiwagi kashiwagi at co-nss.co.jp
+ *
+ * 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/errno.h>
+#include <asm/processor.h>
+
+#define S_DMA_CTRL_BASEADDR XPAR_LLTEMAC_0_LLINK_CONNECTED_BASEADDR
+#define XPS_LLTEMAC_BASEADDR XPAR_LLTEMAC_0_BASEADDR
+
+/* XPS_LL_TEMAC SDMA registers definition */
+

+#define TX_NXTDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x00)
+#define TX_CURBUF_ADDR     (S_DMA_CTRL_BASEADDR + 0x04)
+#define TX_CURBUF_LENGTH   (S_DMA_CTRL_BASEADDR + 0x08)
+#define TX_CURDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x0c)

+#define TX_TAILDESC_PTR (S_DMA_CTRL_BASEADDR + 0x10)
+#define TX_CHNL_CTRL (S_DMA_CTRL_BASEADDR + 0x14)
+#define TX_IRQ_REG (S_DMA_CTRL_BASEADDR + 0x18)
+#define TX_CHNL_STS (S_DMA_CTRL_BASEADDR + 0x1c)
+

+#define RX_NXTDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x20)
+#define RX_CURBUF_ADDR     (S_DMA_CTRL_BASEADDR + 0x24)
+#define RX_CURBUF_LENGTH   (S_DMA_CTRL_BASEADDR + 0x28)
+#define RX_CURDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x2c)

+#define RX_TAILDESC_PTR (S_DMA_CTRL_BASEADDR + 0x30)
+#define RX_CHNL_CTRL (S_DMA_CTRL_BASEADDR + 0x34)
+#define RX_IRQ_REG (S_DMA_CTRL_BASEADDR + 0x38)
+#define RX_CHNL_STS (S_DMA_CTRL_BASEADDR + 0x3c)
+
+#define DMA_CONTROL_REG (S_DMA_CTRL_BASEADDR + 0x40)
+
+/* XPS_LL_TEMAC direct registers definition */
+
+#define TEMAC_RAF0 (XPS_LLTEMAC_BASEADDR + 0x00)
+#define TEMAC_TPF0 (XPS_LLTEMAC_BASEADDR + 0x04)
+#define TEMAC_IFGP0 (XPS_LLTEMAC_BASEADDR + 0x08)

+#define TEMAC_IS0      (XPS_LLTEMAC_BASEADDR + 0x0c)
+#define TEMAC_IP0      (XPS_LLTEMAC_BASEADDR + 0x10)
+#define TEMAC_IE0      (XPS_LLTEMAC_BASEADDR + 0x14)
+
+#define TEMAC_MSW0     (XPS_LLTEMAC_BASEADDR + 0x20)
+#define TEMAC_LSW0     (XPS_LLTEMAC_BASEADDR + 0x24)
+#define TEMAC_CTL0     (XPS_LLTEMAC_BASEADDR + 0x28)
+#define TEMAC_RDY0     (XPS_LLTEMAC_BASEADDR + 0x2c)
+
+#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 RCW0 0x200
+#define RCW1 0x240
+#define TC 0x280

+#define FCC    0x2c0
+#define EMMC   0x300
+#define PHYC   0x320
+#define MC 0x340
+#define UAW0   0x380
+#define UAW1   0x384
+#define MAW0   0x388
+#define MAW1   0x38c
+#define AFM    0x390
+#define TIS    0x3a0
+#define TIE    0x3a4
+#define MIIMWD 0x3b0
+#define MIIMAI 0x3b4
+
+#define CNTLREG_WRITE_ENABLE_MASK  0x8000
+#define CNTLREG_EMAC1SEL_MASK      0x0400
+#define CNTLREG_ADDRESSCODE_MASK   0x03ff

+
+#define MDIO_ENABLE_MASK 0x40
+#define MDIO_CLOCK_DIV_MASK 0x3F
+#define MDIO_CLOCK_DIV_100MHz 0x28
+
+#define ETHER_MTU 1520
+#define CACHE_LINE_SIZE 32
+
+/* SDMA descriptor status bit definitions */
+
+#define BDSTAT_ERROR_MASK 0x80
+#define BDSTAT_INT_ON_END_MASK 0x40
+#define BDSTAT_STOP_ON_END_MASK 0x20

+#define BDSTAT_COMPLETED_MASK   0x10
+#define BDSTAT_SOP_MASK         0x08
+#define BDSTAT_EOP_MASK         0x04
+#define BDSTAT_CHANBUSY_MASK    0x02
+#define BDSTAT_CHANRESET_MASK   0x01

+
+/* SDMA Buffer Descriptor */
+
+typedef 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;

+} cdmac_bd __attribute((aligned(32))) ;
+
+static cdmac_bd tx_bd;
+static cdmac_bd rx_bd;
+static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32))); +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32))); +
+struct xps_ll_temac_private {
+ int idx;
+ unsigned char dev_addr[6];
+};
+
+static void flush_dcache_range(unsigned int addr, unsigned size) +{
+ unsigned int end = addr + size;
+
+ if(size) {
+ addr = addr & ~(CACHE_LINE_SIZE - 1);
+ while(addr < end) {
+ __asm__ __volatile__("dcbf 0,%0; sync;" : : "r" (addr));
+ addr += CACHE_LINE_SIZE;
+ }
+ }
+}
+
+static void invalidate_dcache_range(unsigned int addr, unsigned size) +{
+ unsigned int end = addr + size;
+
+ if(size) {
+ addr = addr & ~(CACHE_LINE_SIZE - 1);
+ while(addr < end) {
+ __asm__ __volatile__("dcbi 0,%0; sync;" : : "r" (addr));
+ addr += CACHE_LINE_SIZE;
+ }
+ }
+}
+
+static unsigned int xps_ll_temac_hostif_get(int emac, int phy_addr, int reg_addr)
+{
+ *(unsigned int *)TEMAC_LSW0 = phy_addr << 5 | reg_addr;
+ *(unsigned int *)TEMAC_CTL0 = MIIMAI | emac << 10;
+
+ while(! (*(volatile unsigned int *)TEMAC_RDY0 & XTE_RSE_MIIM_RR_MASK)
);
+ return *(unsigned int *)TEMAC_LSW0;
+}
+
+static void xps_ll_temac_indirect_set(int emac, int reg_offset, int reg_data)
+{
+ *(unsigned int *)TEMAC_LSW0 = reg_data;
+ *(unsigned int *)TEMAC_CTL0 = CNTLREG_WRITE_ENABLE_MASK | emac << 10
| reg_offset;
+ while(! (*(volatile unsigned int *)TEMAC_RDY0 & XTE_RSE_CFG_WR_MASK))
;
+}
+
+static int xps_ll_temac_phy_ctrl(void)
+{

+   static int phy_addr = -1;
+   static int link = 0;
+   int i;
+   unsigned int result;

+
+ if(phy_addr == -1) {
+ for(i = 0;i < 32;i++) {
+ result = xps_ll_temac_hostif_get(0, i, 1);
+ if((result & 0x0ffff) != 0x0ffff) {
+ phy_addr = i;
+ break;
+ }
+ }
+ } else {
+ result = xps_ll_temac_hostif_get(0, phy_addr, 1);
+ }
+ if((result & 0x24) != 0x24) {
+ if(link) {
+ link = 0;
+ printf("Link down\n");
+ }
+ return 0;
+ }
+ if(link == 0) {
+ link = 1;
+ } else {
+ return 1;
+ }
+
+ result = xps_ll_temac_hostif_get(0, phy_addr, 10);
+ if((result & 0x0800) == 0x0800) {

+       xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
+       printf("1000BASE-T/FD\n");
+       return 1;
+   }
+   result = xps_ll_temac_hostif_get(0, phy_addr, 5);
+   if((result & 0x0100) == 0x0100) {

+ xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
+ printf("100BASE-T/FD\n");
+ } else if((result & 0x0040) == 0x0040) {
+ xps_ll_temac_indirect_set(0, EMMC, 0x00000000);
+ printf("10BASE-T/FD\n");
+ } else {
+ printf("Half Duplex not supported\n");
+ }
+ return 1;
+}
+
+static void xps_ll_temac_bd_init(void)
+{
+ memset((void *)&tx_bd, 0, sizeof(cdmac_bd));
+ memset((void *)&rx_bd, 0, sizeof(cdmac_bd));
+

+   rx_bd.phys_buf_p = &rx_buffer[0];
+   rx_bd.next_p = &rx_bd;
+   rx_bd.buf_len = ETHER_MTU;
+   flush_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)RX_CURDESC_PTR = (unsigned int)&rx_bd;
+   *(unsigned int *)RX_TAILDESC_PTR = (unsigned int)&rx_bd;
+
+   tx_bd.phys_buf_p = &tx_buffer[0];
+   tx_bd.next_p = &tx_bd;
+   flush_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)TX_CURDESC_PTR = (unsigned int)&tx_bd;

+}
+
+static int xps_ll_temac_send(unsigned char *buffer, int length) +{
+ if(xps_ll_temac_phy_ctrl() == 0) return 0;
+
+ memcpy(tx_buffer, buffer, length);
+ flush_dcache_range((unsigned int)tx_buffer, length);
+
+ tx_bd.stat = BDSTAT_SOP_MASK | BDSTAT_EOP_MASK | BDSTAT_STOP_ON_END_
MASK;
+ tx_bd.buf_len = length;
+ flush_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+
+ *(unsigned int *)TX_CURDESC_PTR = (unsigned int)&tx_bd;
+ *(unsigned int *)TX_TAILDESC_PTR = (unsigned int)&tx_bd; /* DMA
start */
+
+ do {
+ invalidate_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+ } while(!((volatile int)tx_bd.stat & BDSTAT_COMPLETED_MASK));
+
+ return length;
+}
+
+static int xps_ll_temac_recv(void)
+{
+ int length;
+
+ invalidate_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+ if(!(rx_bd.stat & BDSTAT_COMPLETED_MASK)) return 0;
+
+ length = rx_bd.app5;
+ invalidate_dcache_range((unsigned int)rx_bd.phys_buf_p, length);
+

+   rx_bd.buf_len = ETHER_MTU;
+   rx_bd.stat = 0;
+   rx_bd.app5 = 0;
+   flush_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)RX_TAILDESC_PTR = (unsigned int)&rx_bd;

+
+ if(length > 0) {
+ NetReceive(rx_bd.phys_buf_p, length);
+ }
+
+ return length;
+}
+
+static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp) +{

+        char * env_p;
+        char * end;
+        int    i, val;

+
+ env_p = getenv("ethaddr");
+ if (env_p == NULL) {
+ printf("cannot get enviroment for \"ethaddr\".\n");
+ return -1;
+ }
+
+ for (i = 0; i < 6; i++) {
+ lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end,
16) : 0;
+ if (env_p) env_p = (*end) ? end + 1 : end;
+ }
+
+ /* set up unicast MAC address filter */
+ val = lp->dev_addr[3] << 24 | lp->dev_addr[2] << 16 |
+ lp->dev_addr[1] << 8 | lp->dev_addr[0];
+ xps_ll_temac_indirect_set(0, UAW0, val);
+ val = lp->dev_addr[5] << 8 | lp->dev_addr[4];
+ xps_ll_temac_indirect_set(0, UAW1, val);
+
+ return 0;
+}
+
+static void xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{
+ struct xps_ll_temac_private *lp = (struct xps_ll_temac_private *)
dev->priv;
+
+ xps_ll_temac_bd_init();
+ xps_ll_temac_indirect_set(0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_
100MHz);
+
+ xps_ll_temac_addr_setup(lp);
+ xps_ll_temac_indirect_set(0, AFM, 0x00000000); /* Promiscuos mode
disable */
+ xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver *
/
+ xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable
Transmitter */
+
+}
+
+int eth_init(bd_t *bis)
+{

+   static int first = 1;
+   struct eth_device *dev;
+   struct xps_ll_temac_private *lp;
+   int i;

+
+ if(!first) return 0;
+ first = 0;
+ dev = (struct eth_device *) calloc(1, sizeof(struct eth_device))
;
+ if (NULL == dev) return 0;
+
+ lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct
xps_ll_temac_private));
+ if (lp == NULL) return 0;
+ dev->priv = lp;
+ sprintf(dev->name, "eth0");
+
+ xps_ll_temac_init(dev, bis);
+
+ printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\
n",
+ dev->name, 0, XPS_LLTEMAC_BASEADDR);
+
+ for(i = 0;i < 3;i++) {
+ if(xps_ll_temac_phy_ctrl()) break;
+ udelay(10000); /* wait second */
+ }
+ return 1;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+ return xps_ll_temac_send((unsigned char *)packet, length);
+}
+
+int eth_rx(void)
+{
+ return xps_ll_temac_recv();
+}
+
+void eth_halt(void)
+{
+}
+

Signature · 1 line
1.5.3.3
#1 lore raw

PATCH 1/1 Xilinx PowerPC XPS_LL_TEMAC driver

Quoted 14 lines · Yoshio Kashiwagi
---
 drivers/net/Makefile          |    1 +
 drivers/net/xilinx_ll_temac.c |  371 ++++++++++++++++++++++++++++++++++
+++++++
 2 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/xilinx_ll_temac.c
drivers/net/Makefile +0 -0
index d5e413b..a11238b 100644

drivers/net/Makefile COBJS-y += uli526x.o · line 66

Quoted 4 lines
drivers/net/Makefile +1 -0
@@ -63,6 +63,7 @@ COBJS-y += uli526x.o
 COBJS-y += vsc7385.o
 COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC)) += xilinx_ll_temac.o
                                  ^

Please remove, it will never compile

use tab for indentation not space
and your patch is line wrapped

Best Regards,
J.

#2 lore raw

PATCH 1/1 Xilinx PowerPC XPS_LL_TEMAC driver

In reply to Yoshio Kashiwagi

Hi Yoshio,

my description is in patch

Quoted 13 lines
---
 drivers/net/Makefile          |    1 +
 drivers/net/xilinx_ll_temac.c |  371 ++++++++++++++++++++++++++++++++++
+++++++
 2 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/xilinx_ll_temac.c
drivers/net/Makefile +0 -0
index d5e413b..a11238b 100644

drivers/net/Makefile COBJS-y += uli526x.o · line 66

Quoted 4 lines
drivers/net/Makefile +1 -0
@@ -63,6 +63,7 @@ COBJS-y += uli526x.o
 COBJS-y += vsc7385.o
 COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC)) += xilinx_ll_temac.o
                                 ^^

two brackets.

Quoted 27 lines
drivers/net/Makefile +0 -0
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
drivers/net/xilinx_ll_temac. renamed from drivers/net/xilinx_ll_temac.c +0 -0

c
new file mode 100644
index 0000000..2f75ebc

drivers/net/xilinx_ll_temac.c new file +11 -0
@@ -0,0 +1,371 @@
+/*
+ *
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * Author: Yoshio Kashiwagi kashiwagi at co-nss.co.jp
+ *
+ * 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.
+ *

drivers/net/xilinx_ll_temac.c

Quoted 6 lines
drivers/net/xilinx_ll_temac.c new file +6 -0
+*/
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <malloc.h>
+#include <asm/errno.h>

you don't use values from errno.h. You can remove it. Microblaze cpu don't have this header too.

Quoted 114 lines
drivers/net/xilinx_ll_temac.c new file +114 -0
+#include <asm/processor.h>
+
+#define S_DMA_CTRL_BASEADDR    XPAR_LLTEMAC_0_LLINK_CONNECTED_BASEADDR
+#define XPS_LLTEMAC_BASEADDR   XPAR_LLTEMAC_0_BASEADDR
+
+/* XPS_LL_TEMAC SDMA registers definition */
+
+#define TX_NXTDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x00)
+#define TX_CURBUF_ADDR     (S_DMA_CTRL_BASEADDR + 0x04)
+#define TX_CURBUF_LENGTH   (S_DMA_CTRL_BASEADDR + 0x08)
+#define TX_CURDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x0c)
+#define TX_TAILDESC_PTR        (S_DMA_CTRL_BASEADDR + 0x10)
+#define TX_CHNL_CTRL       (S_DMA_CTRL_BASEADDR + 0x14)
+#define TX_IRQ_REG     (S_DMA_CTRL_BASEADDR + 0x18)
+#define TX_CHNL_STS        (S_DMA_CTRL_BASEADDR + 0x1c)
+
+#define RX_NXTDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x20)
+#define RX_CURBUF_ADDR     (S_DMA_CTRL_BASEADDR + 0x24)
+#define RX_CURBUF_LENGTH   (S_DMA_CTRL_BASEADDR + 0x28)
+#define RX_CURDESC_PTR     (S_DMA_CTRL_BASEADDR + 0x2c)
+#define RX_TAILDESC_PTR        (S_DMA_CTRL_BASEADDR + 0x30)
+#define RX_CHNL_CTRL       (S_DMA_CTRL_BASEADDR + 0x34)
+#define RX_IRQ_REG     (S_DMA_CTRL_BASEADDR + 0x38)
+#define RX_CHNL_STS        (S_DMA_CTRL_BASEADDR + 0x3c)
+
+#define DMA_CONTROL_REG        (S_DMA_CTRL_BASEADDR + 0x40)
+
+/* XPS_LL_TEMAC direct registers definition */
+
+#define TEMAC_RAF0     (XPS_LLTEMAC_BASEADDR + 0x00)
+#define TEMAC_TPF0     (XPS_LLTEMAC_BASEADDR + 0x04)
+#define TEMAC_IFGP0        (XPS_LLTEMAC_BASEADDR + 0x08)
+#define TEMAC_IS0      (XPS_LLTEMAC_BASEADDR + 0x0c)
+#define TEMAC_IP0      (XPS_LLTEMAC_BASEADDR + 0x10)
+#define TEMAC_IE0      (XPS_LLTEMAC_BASEADDR + 0x14)
+
+#define TEMAC_MSW0     (XPS_LLTEMAC_BASEADDR + 0x20)
+#define TEMAC_LSW0     (XPS_LLTEMAC_BASEADDR + 0x24)
+#define TEMAC_CTL0     (XPS_LLTEMAC_BASEADDR + 0x28)
+#define TEMAC_RDY0     (XPS_LLTEMAC_BASEADDR + 0x2c)
+
+#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 RCW0   0x200
+#define RCW1   0x240
+#define TC 0x280
+#define FCC    0x2c0
+#define EMMC   0x300
+#define PHYC   0x320
+#define MC 0x340
+#define UAW0   0x380
+#define UAW1   0x384
+#define MAW0   0x388
+#define MAW1   0x38c
+#define AFM    0x390
+#define TIS    0x3a0
+#define TIE    0x3a4
+#define MIIMWD 0x3b0
+#define MIIMAI 0x3b4
+
+#define CNTLREG_WRITE_ENABLE_MASK  0x8000
+#define CNTLREG_EMAC1SEL_MASK      0x0400
+#define CNTLREG_ADDRESSCODE_MASK   0x03ff
+
+#define MDIO_ENABLE_MASK   0x40
+#define MDIO_CLOCK_DIV_MASK    0x3F
+#define MDIO_CLOCK_DIV_100MHz  0x28
+
+#define ETHER_MTU      1520
+#define CACHE_LINE_SIZE        32
+
+/* SDMA descriptor status bit definitions */
+
+#define BDSTAT_ERROR_MASK       0x80
+#define BDSTAT_INT_ON_END_MASK  0x40
+#define BDSTAT_STOP_ON_END_MASK 0x20
+#define BDSTAT_COMPLETED_MASK   0x10
+#define BDSTAT_SOP_MASK         0x08
+#define BDSTAT_EOP_MASK         0x04
+#define BDSTAT_CHANBUSY_MASK    0x02
+#define BDSTAT_CHANRESET_MASK   0x01
+
+/* SDMA Buffer Descriptor */
+
+typedef 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;
+} cdmac_bd __attribute((aligned(32))) ;
+
+static cdmac_bd    tx_bd;
+static cdmac_bd    rx_bd;
+static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32)));
+static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
+
+struct xps_ll_temac_private {
+   int idx;
+   unsigned char dev_addr[6];
+};
+
+static void flush_dcache_range(unsigned int addr, unsigned size)
+{

drivers/net/xilinx_ll_temac.c

Quoted 10 lines
drivers/net/xilinx_ll_temac.c new file +10 -0
+   unsigned int end = addr + size;
+
+   if(size) {
+       addr = addr & ~(CACHE_LINE_SIZE - 1);
+       while(addr < end) {
+           __asm__ __volatile__("dcbf 0,%0; sync;" : : "r" (addr));
+           addr += CACHE_LINE_SIZE;
+       }
+   }
+}

Your previous set of patches was better than this style. You can't add assembler code to c code which is not in ppc specific folder. Please use macros for it.

Quoted 231 lines
drivers/net/xilinx_ll_temac.c new file +14 -0
+static void invalidate_dcache_range(unsigned int addr, unsigned size)
+{
+   unsigned int end = addr + size;
+
+   if(size) {
+       addr = addr & ~(CACHE_LINE_SIZE - 1);
+       while(addr < end) {
+           __asm__ __volatile__("dcbi 0,%0; sync;" : : "r" (addr));
+           addr += CACHE_LINE_SIZE;
+       }
+   }
+}
+
+static unsigned int xps_ll_temac_hostif_get(int emac, int phy_addr, int 

reg_addr)

drivers/net/xilinx_ll_temac.c new file +5 -0
+{
+   *(unsigned int *)TEMAC_LSW0 = phy_addr << 5 | reg_addr;
+   *(unsigned int *)TEMAC_CTL0 = MIIMAI | emac << 10;
+
+   while(! (*(volatile unsigned int *)TEMAC_RDY0 & XTE_RSE_MIIM_RR_MASK)

);

drivers/net/xilinx_ll_temac.c new file +4 -0
+   return *(unsigned int *)TEMAC_LSW0;
+}
+
+static void xps_ll_temac_indirect_set(int emac, int reg_offset, int 

reg_data)

drivers/net/xilinx_ll_temac.c new file +3 -0
+{
+   *(unsigned int *)TEMAC_LSW0 = reg_data;
+   *(unsigned int *)TEMAC_CTL0 = CNTLREG_WRITE_ENABLE_MASK | emac << 10 

| reg_offset;
+ while(! (*(volatile unsigned int *)TEMAC_RDY0 & XTE_RSE_CFG_WR_MASK))
;

drivers/net/xilinx_ll_temac.c new file +78 -0
+}
+
+static int xps_ll_temac_phy_ctrl(void)
+{
+   static int phy_addr = -1;
+   static int link = 0;
+   int i;
+   unsigned int result;
+
+   if(phy_addr == -1) {
+       for(i = 0;i < 32;i++) {
+           result = xps_ll_temac_hostif_get(0, i, 1);
+           if((result & 0x0ffff) != 0x0ffff) {
+               phy_addr = i;
+               break;
+           }
+       }
+   } else {
+       result = xps_ll_temac_hostif_get(0, phy_addr, 1);
+   }
+   if((result & 0x24) != 0x24) {
+       if(link) {
+           link = 0;
+           printf("Link down\n");
+       }
+       return 0;
+   }
+   if(link == 0) {
+       link = 1;
+   } else {
+       return 1;
+   }
+
+   result = xps_ll_temac_hostif_get(0, phy_addr, 10);
+   if((result & 0x0800) == 0x0800) {
+       xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
+       printf("1000BASE-T/FD\n");
+       return 1;
+   }
+   result = xps_ll_temac_hostif_get(0, phy_addr, 5);
+   if((result & 0x0100) == 0x0100) {
+       xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
+       printf("100BASE-T/FD\n");
+   } else if((result & 0x0040) == 0x0040) {
+       xps_ll_temac_indirect_set(0, EMMC, 0x00000000);
+       printf("10BASE-T/FD\n");
+   } else {
+       printf("Half Duplex not supported\n");
+   }
+   return 1;
+}
+
+static void xps_ll_temac_bd_init(void)
+{
+   memset((void *)&tx_bd, 0, sizeof(cdmac_bd));
+   memset((void *)&rx_bd, 0, sizeof(cdmac_bd));
+   
+   rx_bd.phys_buf_p = &rx_buffer[0];
+   rx_bd.next_p = &rx_bd;
+   rx_bd.buf_len = ETHER_MTU;
+   flush_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)RX_CURDESC_PTR = (unsigned int)&rx_bd;
+   *(unsigned int *)RX_TAILDESC_PTR = (unsigned int)&rx_bd;
+
+   tx_bd.phys_buf_p = &tx_buffer[0];
+   tx_bd.next_p = &tx_bd;
+   flush_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)TX_CURDESC_PTR = (unsigned int)&tx_bd;
+}
+
+static int xps_ll_temac_send(unsigned char *buffer, int length)
+{
+   if(xps_ll_temac_phy_ctrl() == 0) return 0;
+
+   memcpy(tx_buffer, buffer, length);
+   flush_dcache_range((unsigned int)tx_buffer, length);
+
+   tx_bd.stat = BDSTAT_SOP_MASK | BDSTAT_EOP_MASK | BDSTAT_STOP_ON_END_

MASK;

drivers/net/xilinx_ll_temac.c new file +5 -0
+   tx_bd.buf_len = length;
+   flush_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+
+   *(unsigned int *)TX_CURDESC_PTR = (unsigned int)&tx_bd;
+   *(unsigned int *)TX_TAILDESC_PTR = (unsigned int)&tx_bd; /* DMA 

start */

drivers/net/xilinx_ll_temac.c new file +45 -0
+
+   do {
+       invalidate_dcache_range((unsigned int)&tx_bd, sizeof(cdmac_bd));
+   } while(!((volatile int)tx_bd.stat & BDSTAT_COMPLETED_MASK));
+
+   return length;
+}
+
+static int xps_ll_temac_recv(void)
+{
+   int length;
+
+   invalidate_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+   if(!(rx_bd.stat & BDSTAT_COMPLETED_MASK)) return 0;
+
+   length = rx_bd.app5;
+   invalidate_dcache_range((unsigned int)rx_bd.phys_buf_p, length);
+
+   rx_bd.buf_len = ETHER_MTU;
+   rx_bd.stat = 0;
+   rx_bd.app5 = 0;
+   flush_dcache_range((unsigned int)&rx_bd, sizeof(cdmac_bd));
+   *(unsigned int *)RX_TAILDESC_PTR = (unsigned int)&rx_bd;
+
+   if(length > 0) {
+       NetReceive(rx_bd.phys_buf_p, length);
+   }
+
+   return length;
+}
+
+static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp)
+{
+        char * env_p;
+        char * end;
+        int    i, val;
+
+        env_p = getenv("ethaddr");
+        if (env_p == NULL) {
+                printf("cannot get enviroment for \"ethaddr\".\n");
+                return -1;
+        }
+
+        for (i = 0; i < 6; i++) {
+                lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 

16) : 0;

drivers/net/xilinx_ll_temac.c new file +16 -0
+                if (env_p) env_p = (*end) ? end + 1 : end;
+        }
+
+        /* set up unicast MAC address filter */
+        val = lp->dev_addr[3] << 24 | lp->dev_addr[2] << 16 |
+               lp->dev_addr[1] <<  8 | lp->dev_addr[0];
+   xps_ll_temac_indirect_set(0, UAW0, val);
+        val = lp->dev_addr[5] << 8 |  lp->dev_addr[4];
+   xps_ll_temac_indirect_set(0, UAW1, val);
+
+        return 0;
+}
+
+static void xps_ll_temac_init(struct eth_device *dev, bd_t *bis)
+{
+   struct xps_ll_temac_private *lp = (struct xps_ll_temac_private *)

dev->priv;

drivers/net/xilinx_ll_temac.c new file +3 -0
+
+   xps_ll_temac_bd_init();
+   xps_ll_temac_indirect_set(0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_

100MHz);

drivers/net/xilinx_ll_temac.c new file +3 -0
+   
+   xps_ll_temac_addr_setup(lp);
+   xps_ll_temac_indirect_set(0, AFM, 0x00000000);  /* Promiscuos mode 

disable */
+ xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver *
/
+ xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable
Transmitter */

drivers/net/xilinx_ll_temac.c new file +13 -0
+
+}
+
+int eth_init(bd_t *bis)
+{
+   static int first = 1;
+   struct eth_device *dev;
+   struct xps_ll_temac_private *lp;
+   int i;
+
+   if(!first) return 0;
+   first = 0;
+        dev = (struct eth_device *) calloc(1, sizeof(struct eth_device))

;

drivers/net/xilinx_ll_temac.c new file +3 -0
+        if (NULL == dev) return 0;
+
+        lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct 

xps_ll_temac_private));

drivers/net/xilinx_ll_temac.c new file +7 -0
+        if (lp == NULL) return 0;
+   dev->priv = lp;
+   sprintf(dev->name, "eth0");
+
+   xps_ll_temac_init(dev, bis);
+
+   printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\

n",

drivers/net/xilinx_ll_temac.c new file +13 -0
+       dev->name, 0, XPS_LLTEMAC_BASEADDR);
+
+   for(i = 0;i < 3;i++) {      
+       if(xps_ll_temac_phy_ctrl()) break;
+       udelay(10000);      /* wait second */
+   }
+   return 1;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+   return xps_ll_temac_send((unsigned char *)packet, length);
+}

drivers/net/xilinx_ll_temac.c

Quoted 10 lines
drivers/net/xilinx_ll_temac.c new file +10 -0
+
+int eth_rx(void)
+{
+   return xps_ll_temac_recv();
+}
+
+void eth_halt(void)
+{
+}
+

BTW. Good work. Please clean it and resubmit.
I check it again.

Regards,
Michal Simek