aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ll_temac_main.c
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 /drivers/net/ll_temac_main.c
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>
Diffstat (limited to 'drivers/net/ll_temac_main.c')
-rw-r--r--drivers/net/ll_temac_main.c137
1 files changed, 104 insertions, 33 deletions
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);