aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Linn <john.linn@xilinx.com>2010-04-08 03:08:02 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-13 04:33:44 -0400
commite44171f115de3dedf34064646206deb91549865f (patch)
tree94e7be7a6f9bbc6341a6915a12744ed451dcb75f
parent33646d7ff5f47225cbbf3a06597ded649bf34e8d (diff)
Add non-Virtex5 support for LL TEMAC driver
This patch adds support for using the LL TEMAC Ethernet driver on non-Virtex 5 platforms by adding support for accessing the Soft DMA registers as if they were memory mapped instead of solely through the DCR's (available on the Virtex 5). The patch also updates the driver so that it runs on the MicroBlaze. The changes were tested on the PowerPC 440, PowerPC 405, and the MicroBlaze platforms. Signed-off-by: John Tyner <jtyner@cs.ucr.edu> Signed-off-by: John Linn <john.linn@xilinx.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/microblaze/include/asm/system.h11
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/ll_temac.h14
-rw-r--r--drivers/net/ll_temac_main.c137
4 files changed, 126 insertions, 38 deletions
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
index 59efb3fef957..48c4f0335e3f 100644
--- a/arch/microblaze/include/asm/system.h
+++ b/arch/microblaze/include/asm/system.h
@@ -12,6 +12,7 @@
12#include <asm/registers.h> 12#include <asm/registers.h>
13#include <asm/setup.h> 13#include <asm/setup.h>
14#include <asm/irqflags.h> 14#include <asm/irqflags.h>
15#include <asm/cache.h>
15 16
16#include <asm-generic/cmpxchg.h> 17#include <asm-generic/cmpxchg.h>
17#include <asm-generic/cmpxchg-local.h> 18#include <asm-generic/cmpxchg-local.h>
@@ -96,4 +97,14 @@ extern struct dentry *of_debugfs_root;
96 97
97#define arch_align_stack(x) (x) 98#define arch_align_stack(x) (x)
98 99
100/*
101 * MicroBlaze doesn't handle unaligned accesses in hardware.
102 *
103 * Based on this we force the IP header alignment in network drivers.
104 * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
105 * cacheline alignment of buffers.
106 */
107#define NET_IP_ALIGN 2
108#define NET_SKB_PAD L1_CACHE_BYTES
109
99#endif /* _ASM_MICROBLAZE_SYSTEM_H */ 110#endif /* _ASM_MICROBLAZE_SYSTEM_H */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 49c372a5e0b7..dbd26f992158 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2435,8 +2435,8 @@ config MV643XX_ETH
2435 2435
2436config XILINX_LL_TEMAC 2436config XILINX_LL_TEMAC
2437 tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" 2437 tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
2438 depends on PPC || MICROBLAZE
2438 select PHYLIB 2439 select PHYLIB
2439 depends on PPC_DCR_NATIVE
2440 help 2440 help
2441 This driver supports the Xilinx 10/100/1000 LocalLink TEMAC 2441 This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
2442 core used in Xilinx Spartan and Virtex FPGAs 2442 core used in Xilinx Spartan and Virtex FPGAs
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
index 1af66a1e6911..c03358434acb 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ll_temac.h
@@ -5,8 +5,11 @@
5#include <linux/netdevice.h> 5#include <linux/netdevice.h>
6#include <linux/of.h> 6#include <linux/of.h>
7#include <linux/spinlock.h> 7#include <linux/spinlock.h>
8
9#ifdef CONFIG_PPC_DCR
8#include <asm/dcr.h> 10#include <asm/dcr.h>
9#include <asm/dcr-regs.h> 11#include <asm/dcr-regs.h>
12#endif
10 13
11/* packet size info */ 14/* packet size info */
12#define XTE_HDR_SIZE 14 /* size of Ethernet header */ 15#define XTE_HDR_SIZE 14 /* size of Ethernet header */
@@ -290,9 +293,6 @@ This option defaults to enabled (set) */
290 293
291#define TX_CONTROL_CALC_CSUM_MASK 1 294#define TX_CONTROL_CALC_CSUM_MASK 1
292 295
293#define XTE_ALIGN 32
294#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
295
296#define MULTICAST_CAM_TABLE_NUM 4 296#define MULTICAST_CAM_TABLE_NUM 4
297 297
298/* TX/RX CURDESC_PTR points to first descriptor */ 298/* TX/RX CURDESC_PTR points to first descriptor */
@@ -335,9 +335,15 @@ struct temac_local {
335 struct mii_bus *mii_bus; /* MII bus reference */ 335 struct mii_bus *mii_bus; /* MII bus reference */
336 int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ 336 int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */
337 337
338 /* IO registers and IRQs */ 338 /* IO registers, dma functions and IRQs */
339 void __iomem *regs; 339 void __iomem *regs;
340 void __iomem *sdma_regs;
341#ifdef CONFIG_PPC_DCR
340 dcr_host_t sdma_dcrs; 342 dcr_host_t sdma_dcrs;
343#endif
344 u32 (*dma_in)(struct temac_local *, int);
345 void (*dma_out)(struct temac_local *, int, u32);
346
341 int tx_irq; 347 int tx_irq;
342 int rx_irq; 348 int rx_irq;
343 int emac_num; 349 int emac_num;
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 67765756577d..78c9a2e6e51e 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -20,9 +20,6 @@
20 * or rx, so this should be okay. 20 * or rx, so this should be okay.
21 * 21 *
22 * TODO: 22 * TODO:
23 * - Fix driver to work on more than just Virtex5. Right now the driver
24 * assumes that the locallink DMA registers are accessed via DCR
25 * instructions.
26 * - Factor out locallink DMA code into separate driver 23 * - Factor out locallink DMA code into separate driver
27 * - Fix multicast assignment. 24 * - Fix multicast assignment.
28 * - Fix support for hardware checksumming. 25 * - Fix support for hardware checksumming.
@@ -116,17 +113,86 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
116 temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg); 113 temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
117} 114}
118 115
116/**
117 * temac_dma_in32 - Memory mapped DMA read, this function expects a
118 * register input that is based on DCR word addresses which
119 * are then converted to memory mapped byte addresses
120 */
119static u32 temac_dma_in32(struct temac_local *lp, int reg) 121static u32 temac_dma_in32(struct temac_local *lp, int reg)
120{ 122{
121 return dcr_read(lp->sdma_dcrs, reg); 123 return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
122} 124}
123 125
126/**
127 * temac_dma_out32 - Memory mapped DMA read, this function expects a
128 * register input that is based on DCR word addresses which
129 * are then converted to memory mapped byte addresses
130 */
124static void temac_dma_out32(struct temac_local *lp, int reg, u32 value) 131static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
125{ 132{
133 out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
134}
135
136/* DMA register access functions can be DCR based or memory mapped.
137 * The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
138 * memory mapped.
139 */
140#ifdef CONFIG_PPC_DCR
141
142/**
143 * temac_dma_dcr_in32 - DCR based DMA read
144 */
145static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
146{
147 return dcr_read(lp->sdma_dcrs, reg);
148}
149
150/**
151 * temac_dma_dcr_out32 - DCR based DMA write
152 */
153static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
154{
126 dcr_write(lp->sdma_dcrs, reg, value); 155 dcr_write(lp->sdma_dcrs, reg, value);
127} 156}
128 157
129/** 158/**
159 * temac_dcr_setup - If the DMA is DCR based, then setup the address and
160 * I/O functions
161 */
162static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
163 struct device_node *np)
164{
165 unsigned int dcrs;
166
167 /* setup the dcr address mapping if it's in the device tree */
168
169 dcrs = dcr_resource_start(np, 0);
170 if (dcrs != 0) {
171 lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
172 lp->dma_in = temac_dma_dcr_in;
173 lp->dma_out = temac_dma_dcr_out;
174 dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
175 return 0;
176 }
177 /* no DCR in the device tree, indicate a failure */
178 return -1;
179}
180
181#else
182
183/*
184 * temac_dcr_setup - This is a stub for when DCR is not supported,
185 * such as with MicroBlaze
186 */
187static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
188 struct device_node *np)
189{
190 return -1;
191}
192
193#endif
194
195/**
130 * temac_dma_bd_init - Setup buffer descriptor rings 196 * temac_dma_bd_init - Setup buffer descriptor rings
131 */ 197 */
132static int temac_dma_bd_init(struct net_device *ndev) 198static int temac_dma_bd_init(struct net_device *ndev)
@@ -156,14 +222,14 @@ static int temac_dma_bd_init(struct net_device *ndev)
156 lp->rx_bd_v[i].next = lp->rx_bd_p + 222 lp->rx_bd_v[i].next = lp->rx_bd_p +
157 sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); 223 sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
158 224
159 skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE 225 skb = netdev_alloc_skb_ip_align(ndev,
160 + XTE_ALIGN, GFP_ATOMIC); 226 XTE_MAX_JUMBO_FRAME_SIZE);
227
161 if (skb == 0) { 228 if (skb == 0) {
162 dev_err(&ndev->dev, "alloc_skb error %d\n", i); 229 dev_err(&ndev->dev, "alloc_skb error %d\n", i);
163 return -1; 230 return -1;
164 } 231 }
165 lp->rx_skb[i] = skb; 232 lp->rx_skb[i] = skb;
166 skb_reserve(skb, BUFFER_ALIGN(skb->data));
167 /* returns physical address of skb->data */ 233 /* returns physical address of skb->data */
168 lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, 234 lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
169 skb->data, 235 skb->data,
@@ -173,23 +239,23 @@ static int temac_dma_bd_init(struct net_device *ndev)
173 lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND; 239 lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
174 } 240 }
175 241
176 temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 | 242 lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
177 CHNL_CTRL_IRQ_EN | 243 CHNL_CTRL_IRQ_EN |
178 CHNL_CTRL_IRQ_DLY_EN | 244 CHNL_CTRL_IRQ_DLY_EN |
179 CHNL_CTRL_IRQ_COAL_EN); 245 CHNL_CTRL_IRQ_COAL_EN);
180 /* 0x10220483 */ 246 /* 0x10220483 */
181 /* 0x00100483 */ 247 /* 0x00100483 */
182 temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 | 248 lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
183 CHNL_CTRL_IRQ_EN | 249 CHNL_CTRL_IRQ_EN |
184 CHNL_CTRL_IRQ_DLY_EN | 250 CHNL_CTRL_IRQ_DLY_EN |
185 CHNL_CTRL_IRQ_COAL_EN | 251 CHNL_CTRL_IRQ_COAL_EN |
186 CHNL_CTRL_IRQ_IOE); 252 CHNL_CTRL_IRQ_IOE);
187 /* 0xff010283 */ 253 /* 0xff010283 */
188 254
189 temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p); 255 lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p);
190 temac_dma_out32(lp, RX_TAILDESC_PTR, 256 lp->dma_out(lp, RX_TAILDESC_PTR,
191 lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); 257 lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
192 temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p); 258 lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
193 259
194 return 0; 260 return 0;
195} 261}
@@ -427,9 +493,9 @@ static void temac_device_reset(struct net_device *ndev)
427 temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK); 493 temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
428 494
429 /* Reset Local Link (DMA) */ 495 /* Reset Local Link (DMA) */
430 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); 496 lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
431 timeout = 1000; 497 timeout = 1000;
432 while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { 498 while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
433 udelay(1); 499 udelay(1);
434 if (--timeout == 0) { 500 if (--timeout == 0) {
435 dev_err(&ndev->dev, 501 dev_err(&ndev->dev,
@@ -437,7 +503,7 @@ static void temac_device_reset(struct net_device *ndev)
437 break; 503 break;
438 } 504 }
439 } 505 }
440 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); 506 lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
441 507
442 temac_dma_bd_init(ndev); 508 temac_dma_bd_init(ndev);
443 509
@@ -598,7 +664,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
598 lp->tx_bd_tail = 0; 664 lp->tx_bd_tail = 0;
599 665
600 /* Kick off the transfer */ 666 /* Kick off the transfer */
601 temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ 667 lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
602 668
603 return NETDEV_TX_OK; 669 return NETDEV_TX_OK;
604} 670}
@@ -638,16 +704,15 @@ static void ll_temac_recv(struct net_device *ndev)
638 ndev->stats.rx_packets++; 704 ndev->stats.rx_packets++;
639 ndev->stats.rx_bytes += length; 705 ndev->stats.rx_bytes += length;
640 706
641 new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN, 707 new_skb = netdev_alloc_skb_ip_align(ndev,
642 GFP_ATOMIC); 708 XTE_MAX_JUMBO_FRAME_SIZE);
709
643 if (new_skb == 0) { 710 if (new_skb == 0) {
644 dev_err(&ndev->dev, "no memory for new sk_buff\n"); 711 dev_err(&ndev->dev, "no memory for new sk_buff\n");
645 spin_unlock_irqrestore(&lp->rx_lock, flags); 712 spin_unlock_irqrestore(&lp->rx_lock, flags);
646 return; 713 return;
647 } 714 }
648 715
649 skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data));
650
651 cur_p->app0 = STS_CTRL_APP0_IRQONEND; 716 cur_p->app0 = STS_CTRL_APP0_IRQONEND;
652 cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, 717 cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
653 XTE_MAX_JUMBO_FRAME_SIZE, 718 XTE_MAX_JUMBO_FRAME_SIZE,
@@ -662,7 +727,7 @@ static void ll_temac_recv(struct net_device *ndev)
662 cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; 727 cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
663 bdstat = cur_p->app0; 728 bdstat = cur_p->app0;
664 } 729 }
665 temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p); 730 lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
666 731
667 spin_unlock_irqrestore(&lp->rx_lock, flags); 732 spin_unlock_irqrestore(&lp->rx_lock, flags);
668} 733}
@@ -673,8 +738,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
673 struct temac_local *lp = netdev_priv(ndev); 738 struct temac_local *lp = netdev_priv(ndev);
674 unsigned int status; 739 unsigned int status;
675 740
676 status = temac_dma_in32(lp, TX_IRQ_REG); 741 status = lp->dma_in(lp, TX_IRQ_REG);
677 temac_dma_out32(lp, TX_IRQ_REG, status); 742 lp->dma_out(lp, TX_IRQ_REG, status);
678 743
679 if (status & (IRQ_COAL | IRQ_DLY)) 744 if (status & (IRQ_COAL | IRQ_DLY))
680 temac_start_xmit_done(lp->ndev); 745 temac_start_xmit_done(lp->ndev);
@@ -691,8 +756,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
691 unsigned int status; 756 unsigned int status;
692 757
693 /* Read and clear the status registers */ 758 /* Read and clear the status registers */
694 status = temac_dma_in32(lp, RX_IRQ_REG); 759 status = lp->dma_in(lp, RX_IRQ_REG);
695 temac_dma_out32(lp, RX_IRQ_REG, status); 760 lp->dma_out(lp, RX_IRQ_REG, status);
696 761
697 if (status & (IRQ_COAL | IRQ_DLY)) 762 if (status & (IRQ_COAL | IRQ_DLY))
698 ll_temac_recv(lp->ndev); 763 ll_temac_recv(lp->ndev);
@@ -793,7 +858,7 @@ static ssize_t temac_show_llink_regs(struct device *dev,
793 int i, len = 0; 858 int i, len = 0;
794 859
795 for (i = 0; i < 0x11; i++) 860 for (i = 0; i < 0x11; i++)
796 len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i), 861 len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
797 (i % 8) == 7 ? "\n" : " "); 862 (i % 8) == 7 ? "\n" : " ");
798 len += sprintf(buf + len, "\n"); 863 len += sprintf(buf + len, "\n");
799 864
@@ -819,7 +884,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
819 struct net_device *ndev; 884 struct net_device *ndev;
820 const void *addr; 885 const void *addr;
821 int size, rc = 0; 886 int size, rc = 0;
822 unsigned int dcrs;
823 887
824 /* Init network device structure */ 888 /* Init network device structure */
825 ndev = alloc_etherdev(sizeof(*lp)); 889 ndev = alloc_etherdev(sizeof(*lp));
@@ -869,13 +933,20 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
869 goto nodev; 933 goto nodev;
870 } 934 }
871 935
872 dcrs = dcr_resource_start(np, 0); 936 /* Setup the DMA register accesses, could be DCR or memory mapped */
873 if (dcrs == 0) { 937 if (temac_dcr_setup(lp, op, np)) {
874 dev_err(&op->dev, "could not get DMA register address\n"); 938
875 goto nodev; 939 /* no DCR in the device tree, try non-DCR */
940 lp->sdma_regs = of_iomap(np, 0);
941 if (lp->sdma_regs) {
942 lp->dma_in = temac_dma_in32;
943 lp->dma_out = temac_dma_out32;
944 dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
945 } else {
946 dev_err(&op->dev, "unable to map DMA registers\n");
947 goto nodev;
948 }
876 } 949 }
877 lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
878 dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
879 950
880 lp->rx_irq = irq_of_parse_and_map(np, 0); 951 lp->rx_irq = irq_of_parse_and_map(np, 0);
881 lp->tx_irq = irq_of_parse_and_map(np, 1); 952 lp->tx_irq = irq_of_parse_and_map(np, 1);