aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohn Linn <john.linn@xilinx.com>2010-04-06 07:43:28 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-06 22:50:19 -0400
commit459569145516f7967b916c57445feb02c600668c (patch)
tree421c7eb8f9888d0c9b4e7eabc29f654e69fa035a /drivers/net
parent3a7f8681ffb27bcc540fb74cda15e39c9395737b (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> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/ll_temac.h14
-rw-r--r--drivers/net/ll_temac_main.c137
3 files changed, 115 insertions, 38 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a55bff26a264..20e2dec1d534 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 30474d6b15c3..b6edb2fd0a8a 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.
@@ -115,17 +112,86 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
115 temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg); 112 temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
116} 113}
117 114
115/**
116 * temac_dma_in32 - Memory mapped DMA read, this function expects a
117 * register input that is based on DCR word addresses which
118 * are then converted to memory mapped byte addresses
119 */
118static u32 temac_dma_in32(struct temac_local *lp, int reg) 120static u32 temac_dma_in32(struct temac_local *lp, int reg)
119{ 121{
120 return dcr_read(lp->sdma_dcrs, reg); 122 return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
121} 123}
122 124
125/**
126 * temac_dma_out32 - Memory mapped DMA read, this function expects a
127 * register input that is based on DCR word addresses which
128 * are then converted to memory mapped byte addresses
129 */
123static void temac_dma_out32(struct temac_local *lp, int reg, u32 value) 130static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
124{ 131{
132 out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
133}
134
135/* DMA register access functions can be DCR based or memory mapped.
136 * The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
137 * memory mapped.
138 */
139#ifdef CONFIG_PPC_DCR
140
141/**
142 * temac_dma_dcr_in32 - DCR based DMA read
143 */
144static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
145{
146 return dcr_read(lp->sdma_dcrs, reg);
147}
148
149/**
150 * temac_dma_dcr_out32 - DCR based DMA write
151 */
152static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
153{
125 dcr_write(lp->sdma_dcrs, reg, value); 154 dcr_write(lp->sdma_dcrs, reg, value);
126} 155}
127 156
128/** 157/**
158 * temac_dcr_setup - If the DMA is DCR based, then setup the address and
159 * I/O functions
160 */
161static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
162 struct device_node *np)
163{
164 unsigned int dcrs;
165
166 /* setup the dcr address mapping if it's in the device tree */
167
168 dcrs = dcr_resource_start(np, 0);
169 if (dcrs != 0) {
170 lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
171 lp->dma_in = temac_dma_dcr_in;
172 lp->dma_out = temac_dma_dcr_out;
173 dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
174 return 0;
175 }
176 /* no DCR in the device tree, indicate a failure */
177 return -1;
178}
179
180#else
181
182/*
183 * temac_dcr_setup - This is a stub for when DCR is not supported,
184 * such as with MicroBlaze
185 */
186static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
187 struct device_node *np)
188{
189 return -1;
190}
191
192#endif
193
194/**
129 * temac_dma_bd_init - Setup buffer descriptor rings 195 * temac_dma_bd_init - Setup buffer descriptor rings
130 */ 196 */
131static int temac_dma_bd_init(struct net_device *ndev) 197static int temac_dma_bd_init(struct net_device *ndev)
@@ -155,14 +221,14 @@ static int temac_dma_bd_init(struct net_device *ndev)
155 lp->rx_bd_v[i].next = lp->rx_bd_p + 221 lp->rx_bd_v[i].next = lp->rx_bd_p +
156 sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); 222 sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
157 223
158 skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE 224 skb = netdev_alloc_skb_ip_align(ndev,
159 + XTE_ALIGN, GFP_ATOMIC); 225 XTE_MAX_JUMBO_FRAME_SIZE);
226
160 if (skb == 0) { 227 if (skb == 0) {
161 dev_err(&ndev->dev, "alloc_skb error %d\n", i); 228 dev_err(&ndev->dev, "alloc_skb error %d\n", i);
162 return -1; 229 return -1;
163 } 230 }
164 lp->rx_skb[i] = skb; 231 lp->rx_skb[i] = skb;
165 skb_reserve(skb, BUFFER_ALIGN(skb->data));
166 /* returns physical address of skb->data */ 232 /* returns physical address of skb->data */
167 lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, 233 lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
168 skb->data, 234 skb->data,
@@ -172,23 +238,23 @@ static int temac_dma_bd_init(struct net_device *ndev)
172 lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND; 238 lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
173 } 239 }
174 240
175 temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 | 241 lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
176 CHNL_CTRL_IRQ_EN | 242 CHNL_CTRL_IRQ_EN |
177 CHNL_CTRL_IRQ_DLY_EN | 243 CHNL_CTRL_IRQ_DLY_EN |
178 CHNL_CTRL_IRQ_COAL_EN); 244 CHNL_CTRL_IRQ_COAL_EN);
179 /* 0x10220483 */ 245 /* 0x10220483 */
180 /* 0x00100483 */ 246 /* 0x00100483 */
181 temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 | 247 lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
182 CHNL_CTRL_IRQ_EN | 248 CHNL_CTRL_IRQ_EN |
183 CHNL_CTRL_IRQ_DLY_EN | 249 CHNL_CTRL_IRQ_DLY_EN |
184 CHNL_CTRL_IRQ_COAL_EN | 250 CHNL_CTRL_IRQ_COAL_EN |
185 CHNL_CTRL_IRQ_IOE); 251 CHNL_CTRL_IRQ_IOE);
186 /* 0xff010283 */ 252 /* 0xff010283 */
187 253
188 temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p); 254 lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p);
189 temac_dma_out32(lp, RX_TAILDESC_PTR, 255 lp->dma_out(lp, RX_TAILDESC_PTR,
190 lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); 256 lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
191 temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p); 257 lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
192 258
193 return 0; 259 return 0;
194} 260}
@@ -426,9 +492,9 @@ static void temac_device_reset(struct net_device *ndev)
426 temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK); 492 temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
427 493
428 /* Reset Local Link (DMA) */ 494 /* Reset Local Link (DMA) */
429 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); 495 lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
430 timeout = 1000; 496 timeout = 1000;
431 while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { 497 while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
432 udelay(1); 498 udelay(1);
433 if (--timeout == 0) { 499 if (--timeout == 0) {
434 dev_err(&ndev->dev, 500 dev_err(&ndev->dev,
@@ -436,7 +502,7 @@ static void temac_device_reset(struct net_device *ndev)
436 break; 502 break;
437 } 503 }
438 } 504 }
439 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); 505 lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
440 506
441 temac_dma_bd_init(ndev); 507 temac_dma_bd_init(ndev);
442 508
@@ -597,7 +663,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
597 lp->tx_bd_tail = 0; 663 lp->tx_bd_tail = 0;
598 664
599 /* Kick off the transfer */ 665 /* Kick off the transfer */
600 temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ 666 lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
601 667
602 return NETDEV_TX_OK; 668 return NETDEV_TX_OK;
603} 669}
@@ -639,16 +705,15 @@ static void ll_temac_recv(struct net_device *ndev)
639 ndev->stats.rx_packets++; 705 ndev->stats.rx_packets++;
640 ndev->stats.rx_bytes += length; 706 ndev->stats.rx_bytes += length;
641 707
642 new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN, 708 new_skb = netdev_alloc_skb_ip_align(ndev,
643 GFP_ATOMIC); 709 XTE_MAX_JUMBO_FRAME_SIZE);
710
644 if (new_skb == 0) { 711 if (new_skb == 0) {
645 dev_err(&ndev->dev, "no memory for new sk_buff\n"); 712 dev_err(&ndev->dev, "no memory for new sk_buff\n");
646 spin_unlock_irqrestore(&lp->rx_lock, flags); 713 spin_unlock_irqrestore(&lp->rx_lock, flags);
647 return; 714 return;
648 } 715 }
649 716
650 skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data));
651
652 cur_p->app0 = STS_CTRL_APP0_IRQONEND; 717 cur_p->app0 = STS_CTRL_APP0_IRQONEND;
653 cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, 718 cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
654 XTE_MAX_JUMBO_FRAME_SIZE, 719 XTE_MAX_JUMBO_FRAME_SIZE,
@@ -663,7 +728,7 @@ static void ll_temac_recv(struct net_device *ndev)
663 cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; 728 cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
664 bdstat = cur_p->app0; 729 bdstat = cur_p->app0;
665 } 730 }
666 temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p); 731 lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
667 732
668 spin_unlock_irqrestore(&lp->rx_lock, flags); 733 spin_unlock_irqrestore(&lp->rx_lock, flags);
669} 734}
@@ -674,8 +739,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
674 struct temac_local *lp = netdev_priv(ndev); 739 struct temac_local *lp = netdev_priv(ndev);
675 unsigned int status; 740 unsigned int status;
676 741
677 status = temac_dma_in32(lp, TX_IRQ_REG); 742 status = lp->dma_in(lp, TX_IRQ_REG);
678 temac_dma_out32(lp, TX_IRQ_REG, status); 743 lp->dma_out(lp, TX_IRQ_REG, status);
679 744
680 if (status & (IRQ_COAL | IRQ_DLY)) 745 if (status & (IRQ_COAL | IRQ_DLY))
681 temac_start_xmit_done(lp->ndev); 746 temac_start_xmit_done(lp->ndev);
@@ -692,8 +757,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
692 unsigned int status; 757 unsigned int status;
693 758
694 /* Read and clear the status registers */ 759 /* Read and clear the status registers */
695 status = temac_dma_in32(lp, RX_IRQ_REG); 760 status = lp->dma_in(lp, RX_IRQ_REG);
696 temac_dma_out32(lp, RX_IRQ_REG, status); 761 lp->dma_out(lp, RX_IRQ_REG, status);
697 762
698 if (status & (IRQ_COAL | IRQ_DLY)) 763 if (status & (IRQ_COAL | IRQ_DLY))
699 ll_temac_recv(lp->ndev); 764 ll_temac_recv(lp->ndev);
@@ -794,7 +859,7 @@ static ssize_t temac_show_llink_regs(struct device *dev,
794 int i, len = 0; 859 int i, len = 0;
795 860
796 for (i = 0; i < 0x11; i++) 861 for (i = 0; i < 0x11; i++)
797 len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i), 862 len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
798 (i % 8) == 7 ? "\n" : " "); 863 (i % 8) == 7 ? "\n" : " ");
799 len += sprintf(buf + len, "\n"); 864 len += sprintf(buf + len, "\n");
800 865
@@ -820,7 +885,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
820 struct net_device *ndev; 885 struct net_device *ndev;
821 const void *addr; 886 const void *addr;
822 int size, rc = 0; 887 int size, rc = 0;
823 unsigned int dcrs;
824 888
825 /* Init network device structure */ 889 /* Init network device structure */
826 ndev = alloc_etherdev(sizeof(*lp)); 890 ndev = alloc_etherdev(sizeof(*lp));
@@ -870,13 +934,20 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
870 goto nodev; 934 goto nodev;
871 } 935 }
872 936
873 dcrs = dcr_resource_start(np, 0); 937 /* Setup the DMA register accesses, could be DCR or memory mapped */
874 if (dcrs == 0) { 938 if (temac_dcr_setup(lp, op, np)) {
875 dev_err(&op->dev, "could not get DMA register address\n"); 939
876 goto nodev; 940 /* no DCR in the device tree, try non-DCR */
941 lp->sdma_regs = of_iomap(np, 0);
942 if (lp->sdma_regs) {
943 lp->dma_in = temac_dma_in32;
944 lp->dma_out = temac_dma_out32;
945 dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
946 } else {
947 dev_err(&op->dev, "unable to map DMA registers\n");
948 goto nodev;
949 }
877 } 950 }
878 lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
879 dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
880 951
881 lp->rx_irq = irq_of_parse_and_map(np, 0); 952 lp->rx_irq = irq_of_parse_and_map(np, 0);
882 lp->tx_irq = irq_of_parse_and_map(np, 1); 953 lp->tx_irq = irq_of_parse_and_map(np, 1);