Xilinx PowerPC XPS_LL_TEMAC driver
Subsystems (2)
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
@@ -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(structxps_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
PATCH 1/1 Xilinx PowerPC XPS_LL_TEMAC driver
Quoted 14 lines · Yoshio Kashiwagi
Signed-off-by Yoshio Kashiwagi <[email protected]>--- 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.cdrivers/net/Makefile +0
-0
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.
PATCH 1/1 Xilinx PowerPC XPS_LL_TEMAC driver
In reply to Yoshio KashiwagiHi Yoshio,
my description is in patch
Quoted 13 lines
Signed-off-by Yoshio Kashiwagi <[email protected]>--- 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.cdrivers/net/Makefile +0
-0
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
-0COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c)drivers/net/xilinx_ll_temac. renamed from drivers/net/xilinx_ll_temac.c +0
-0c
new file mode 100644
index 0000000..2f75ebcdrivers/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