Root/target/linux/brcm63xx/patches-3.3/415-bcm63xx_enet-add-support-for-bcm6368-internal-ethern.patch

1From 1324bb5db6815d19b09c1b7bcac3cc2804412205 Mon Sep 17 00:00:00 2001
2From: Maxime Bizon <mbizon@freebox.fr>
3Date: Sat, 23 Jan 2010 03:01:02 +0100
4Subject: [PATCH 31/63] bcm63xx_enet: add support for bcm6368 internal ethernet switch.
5
6---
7 arch/mips/bcm63xx/dev-enet.c | 106 ++-
8 .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 25 +
9 arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 50 +
10 drivers/net/ethernet/broadcom/bcm63xx_enet.c | 1054 ++++++++++++++++++--
11 drivers/net/ethernet/broadcom/bcm63xx_enet.h | 71 ++
12 5 files changed, 1221 insertions(+), 85 deletions(-)
13
14--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
15+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
16@@ -920,6 +920,10 @@ int __init board_register_devices(void)
17         !board_get_mac_address(board.enet1.mac_addr))
18         bcm63xx_enet_register(1, &board.enet1);
19 
20+ if (board.has_enetsw &&
21+ !board_get_mac_address(board.enetsw.mac_addr))
22+ bcm63xx_enetsw_register(&board.enetsw);
23+
24     if (board.has_ehci0)
25         bcm63xx_ehci_register();
26 
27--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
28+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
29@@ -41,6 +41,7 @@ struct board_info {
30     /* enabled feature/device */
31     unsigned int has_enet0:1;
32     unsigned int has_enet1:1;
33+ unsigned int has_enetsw:1;
34     unsigned int has_pci:1;
35     unsigned int has_pccard:1;
36     unsigned int has_ohci0:1;
37@@ -52,6 +53,7 @@ struct board_info {
38     /* ethernet config */
39     struct bcm63xx_enet_platform_data enet0;
40     struct bcm63xx_enet_platform_data enet1;
41+ struct bcm63xx_enetsw_platform_data enetsw;
42 
43     /* DSP config */
44     struct bcm63xx_dsp_platform_data dsp;
45--- a/arch/mips/bcm63xx/dev-enet.c
46+++ b/arch/mips/bcm63xx/dev-enet.c
47@@ -104,6 +104,64 @@ static struct platform_device bcm63xx_en
48     },
49 };
50 
51+static struct resource enetsw_res[] = {
52+ {
53+ /* start & end filled at runtime */
54+ .flags = IORESOURCE_MEM,
55+ },
56+ {
57+ /* start filled at runtime */
58+ .flags = IORESOURCE_IRQ,
59+ },
60+ {
61+ /* start filled at runtime */
62+ .flags = IORESOURCE_IRQ,
63+ },
64+};
65+
66+static struct bcm63xx_enetsw_platform_data enetsw_pd;
67+
68+static struct platform_device bcm63xx_enetsw_device = {
69+ .name = "bcm63xx_enetsw",
70+ .num_resources = ARRAY_SIZE(enetsw_res),
71+ .resource = enetsw_res,
72+ .dev = {
73+ .platform_data = &enetsw_pd,
74+ },
75+};
76+
77+static int __init register_shared(void)
78+{
79+ int ret, chan_count;
80+
81+ if (shared_device_registered)
82+ return 0;
83+
84+ shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
85+ shared_res[0].end = shared_res[0].start;
86+ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
87+
88+ if (BCMCPU_IS_6368())
89+ chan_count = 32;
90+ else
91+ chan_count = 16;
92+
93+ shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
94+ shared_res[1].end = shared_res[1].start;
95+ shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
96+
97+ shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
98+ shared_res[2].end = shared_res[2].start;
99+ shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
100+
101+ ret = platform_device_register(&bcm63xx_enet_shared_device);
102+ if (ret)
103+ return ret;
104+ shared_device_registered = 1;
105+
106+ return 0;
107+}
108+
109 int __init bcm63xx_enet_register(int unit,
110                  const struct bcm63xx_enet_platform_data *pd)
111 {
112@@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int uni
113     if (unit == 1 && BCMCPU_IS_6338())
114         return -ENODEV;
115 
116- if (!shared_device_registered) {
117- shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
118- shared_res[0].end = shared_res[0].start;
119- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
120-
121- shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
122- shared_res[1].end = shared_res[1].start;
123- shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
124-
125- shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
126- shared_res[2].end = shared_res[2].start;
127- shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
128-
129- ret = platform_device_register(&bcm63xx_enet_shared_device);
130- if (ret)
131- return ret;
132- shared_device_registered = 1;
133- }
134+ ret = register_shared();
135+ if (ret)
136+ return ret;
137 
138     if (unit == 0) {
139         enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
140@@ -175,3 +218,30 @@ int __init bcm63xx_enet_register(int uni
141         return ret;
142     return 0;
143 }
144+
145+int __init
146+bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
147+{
148+ int ret;
149+
150+ if (!BCMCPU_IS_6368())
151+ return -ENODEV;
152+
153+ ret = register_shared();
154+ if (ret)
155+ return ret;
156+
157+ enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
158+ enetsw_res[0].end = enetsw_res[0].start;
159+ enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
160+ enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
161+ enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
162+
163+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
164+
165+ ret = platform_device_register(&bcm63xx_enetsw_device);
166+ if (ret)
167+ return ret;
168+
169+ return 0;
170+}
171--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
172+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
173@@ -39,7 +39,32 @@ struct bcm63xx_enet_platform_data {
174                         int phy_id, int reg, int val));
175 };
176 
177+/*
178+ * on board ethernet switch platform data
179+ */
180+#define ENETSW_MAX_PORT 6
181+
182+struct bcm63xx_enetsw_port {
183+ int used;
184+ int external_phy;
185+ int phy_id;
186+
187+ int bypass_link;
188+ int force_speed;
189+ int force_duplex_full;
190+
191+ const char *name;
192+};
193+
194+struct bcm63xx_enetsw_platform_data {
195+ char mac_addr[ETH_ALEN];
196+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
197+};
198+
199 int __init bcm63xx_enet_register(int unit,
200                  const struct bcm63xx_enet_platform_data *pd);
201 
202+int __init
203+bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd);
204+
205 #endif /* ! BCM63XX_DEV_ENET_H_ */
206--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
207+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
208@@ -809,10 +809,60 @@
209  * _REG relative to RSET_ENETSW
210  *************************************************************************/
211 
212+/* Port traffic control */
213+#define ENETSW_PTCTRL_REG(x) (0x0 + (x))
214+#define ENETSW_PTCTRL_RXDIS_MASK (1 << 0)
215+#define ENETSW_PTCTRL_TXDIS_MASK (1 << 1)
216+
217+/* Switch mode register */
218+#define ENETSW_SWMODE_REG (0xb)
219+#define ENETSW_SWMODE_FWD_EN_MASK (1 << 1)
220+
221+/* IMP override Register */
222+#define ENETSW_IMPOV_REG (0xe)
223+#define ENETSW_IMPOV_FORCE_MASK (1 << 7)
224+#define ENETSW_IMPOV_TXFLOW_MASK (1 << 5)
225+#define ENETSW_IMPOV_RXFLOW_MASK (1 << 4)
226+#define ENETSW_IMPOV_1000_MASK (1 << 3)
227+#define ENETSW_IMPOV_100_MASK (1 << 2)
228+#define ENETSW_IMPOV_FDX_MASK (1 << 1)
229+#define ENETSW_IMPOV_LINKUP_MASK (1 << 0)
230+
231+/* Port override Register */
232+#define ENETSW_PORTOV_REG(x) (0x58 + (x))
233+#define ENETSW_PORTOV_ENABLE_MASK (1 << 6)
234+#define ENETSW_PORTOV_TXFLOW_MASK (1 << 5)
235+#define ENETSW_PORTOV_RXFLOW_MASK (1 << 4)
236+#define ENETSW_PORTOV_1000_MASK (1 << 3)
237+#define ENETSW_PORTOV_100_MASK (1 << 2)
238+#define ENETSW_PORTOV_FDX_MASK (1 << 1)
239+#define ENETSW_PORTOV_LINKUP_MASK (1 << 0)
240+
241+/* MDIO control register */
242+#define ENETSW_MDIOC_REG (0xb0)
243+#define ENETSW_MDIOC_EXT_MASK (1 << 16)
244+#define ENETSW_MDIOC_REG_SHIFT 20
245+#define ENETSW_MDIOC_PHYID_SHIFT 25
246+#define ENETSW_MDIOC_RD_MASK (1 << 30)
247+#define ENETSW_MDIOC_WR_MASK (1 << 31)
248+
249+/* MDIO data register */
250+#define ENETSW_MDIOD_REG (0xb4)
251+
252+/* Global Management Configuration Register */
253+#define ENETSW_GMCR_REG (0x200)
254+#define ENETSW_GMCR_RST_MIB_MASK (1 << 0)
255+
256 /* MIB register */
257 #define ENETSW_MIB_REG(x) (0x2800 + (x) * 4)
258 #define ENETSW_MIB_REG_COUNT 47
259 
260+/* Jumbo control register port mask register */
261+#define ENETSW_JMBCTL_PORT_REG (0x4004)
262+
263+/* Jumbo control mib good frame register */
264+#define ENETSW_JMBCTL_MAXSIZE_REG (0x4008)
265+
266 
267 /*************************************************************************
268  * _REG relative to RSET_OHCI_PRIV
269--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
270+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
271@@ -59,6 +59,49 @@ static inline void enet_writel(struct bc
272 }
273 
274 /*
275+ * io helpers to access switch registers
276+ */
277+static inline u32 enetsw_readl(struct bcm_enet_priv *priv, u32 off)
278+{
279+ /* printk("enetsw_readl at %p\n", priv->base + off); */
280+ return bcm_readl(priv->base + off);
281+}
282+
283+static inline void enetsw_writel(struct bcm_enet_priv *priv,
284+ u32 val, u32 off)
285+{
286+ /* printk("enetsw_writel %08x at %p\n", val, priv->base + off); */
287+ bcm_writel(val, priv->base + off);
288+}
289+
290+static inline u16 enetsw_readw(struct bcm_enet_priv *priv, u32 off)
291+{
292+ /* printk("enetsw_readw at %p\n", priv->base + off); */
293+ return bcm_readw(priv->base + off);
294+}
295+
296+static inline void enetsw_writew(struct bcm_enet_priv *priv,
297+ u16 val, u32 off)
298+{
299+ /* printk("enetsw_writew %04x at %p\n", val, priv->base + off); */
300+ bcm_writew(val, priv->base + off);
301+}
302+
303+static inline u8 enetsw_readb(struct bcm_enet_priv *priv, u32 off)
304+{
305+ /* printk("enetsw_readb at %p\n", priv->base + off); */
306+ return bcm_readb(priv->base + off);
307+}
308+
309+static inline void enetsw_writeb(struct bcm_enet_priv *priv,
310+ u8 val, u32 off)
311+{
312+ /* printk("enetsw_writeb %02x at %p\n", val, priv->base + off); */
313+ bcm_writeb(val, priv->base + off);
314+}
315+
316+
317+/*
318  * io helpers to access shared registers
319  */
320 static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off)
321@@ -321,7 +364,8 @@ static int bcm_enet_receive_queue(struct
322         }
323 
324         /* recycle packet if it's marked as bad */
325- if (unlikely(len_stat & DMADESC_ERR_MASK)) {
326+ if (!bcm_enet_is_sw(priv) &&
327+ unlikely(len_stat & DMADESC_ERR_MASK)) {
328             dev->stats.rx_errors++;
329 
330             if (len_stat & DMADESC_OVSIZE_MASK)
331@@ -552,6 +596,26 @@ static int bcm_enet_start_xmit(struct sk
332         goto out_unlock;
333     }
334 
335+ /* pad small packets sent on a switch device */
336+ if (bcm_enet_is_sw(priv) && skb->len < 64) {
337+ int needed = 64 - skb->len;
338+ char *data;
339+
340+ if (unlikely(skb_tailroom(skb) < needed)) {
341+ struct sk_buff *nskb;
342+
343+ nskb = skb_copy_expand(skb, 0, needed, GFP_ATOMIC);
344+ if (!nskb) {
345+ ret = NETDEV_TX_BUSY;
346+ goto out_unlock;
347+ }
348+ dev_kfree_skb(skb);
349+ skb = nskb;
350+ }
351+ data = skb_put(skb, needed);
352+ memset(data, 0, needed);
353+ }
354+
355     /* point to the next available desc */
356     desc = &priv->tx_desc_cpu[priv->tx_curr_desc];
357     priv->tx_skb[priv->tx_curr_desc] = skb;
358@@ -1921,96 +1985,951 @@ struct platform_driver bcm63xx_enet_driv
359 };
360 
361 /*
362- * reserve & remap memory space shared between all macs
363+ * switch mii access callbacks
364  */
365-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
366+static int bcmenet_sw_mdio_read(struct bcm_enet_priv *priv,
367+ int ext, int phy_id, int location)
368 {
369- struct resource *res;
370- int ret, i, requested[3];
371+ u32 reg;
372+ int ret;
373 
374- memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base));
375- memset(requested, 0, sizeof (requested));
376+ spin_lock_bh(&priv->enetsw_mdio_lock);
377+ enetsw_writel(priv, 0, ENETSW_MDIOC_REG);
378 
379- for (i = 0; i < 3; i++) {
380- void __iomem *p;
381+ reg = ENETSW_MDIOC_RD_MASK |
382+ (phy_id << ENETSW_MDIOC_PHYID_SHIFT) |
383+ (location << ENETSW_MDIOC_REG_SHIFT);
384+
385+ if (ext)
386+ reg |= ENETSW_MDIOC_EXT_MASK;
387+
388+ enetsw_writel(priv, reg, ENETSW_MDIOC_REG);
389+ udelay(50);
390+ ret = enetsw_readw(priv, ENETSW_MDIOD_REG);
391+ spin_unlock_bh(&priv->enetsw_mdio_lock);
392+ return ret;
393+}
394 
395- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
396- if (!res) {
397- ret = -EINVAL;
398- goto fail;
399- }
400+static void bcmenet_sw_mdio_write(struct bcm_enet_priv *priv,
401+ int ext, int phy_id, int location,
402+ uint16_t data)
403+{
404+ u32 reg;
405 
406- if (!request_mem_region(res->start, resource_size(res),
407- "bcm63xx_enet_dma")) {
408- ret = -EBUSY;
409- goto fail;
410- }
411- requested[i] = 0;
412+ spin_lock_bh(&priv->enetsw_mdio_lock);
413+ enetsw_writel(priv, 0, ENETSW_MDIOC_REG);
414 
415- p = ioremap(res->start, resource_size(res));
416- if (!p) {
417- ret = -ENOMEM;
418- goto fail;
419- }
420+ reg = ENETSW_MDIOC_WR_MASK |
421+ (phy_id << ENETSW_MDIOC_PHYID_SHIFT) |
422+ (location << ENETSW_MDIOC_REG_SHIFT);
423 
424- bcm_enet_shared_base[i] = p;
425- }
426+ if (ext)
427+ reg |= ENETSW_MDIOC_EXT_MASK;
428 
429- return 0;
430+ reg |= data;
431 
432-fail:
433- for (i = 0; i < 3; i++) {
434- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
435- if (!res)
436- continue;
437- if (bcm_enet_shared_base[i])
438- iounmap(bcm_enet_shared_base[i]);
439- if (requested[i])
440- release_mem_region(res->start, resource_size(res));
441- }
442- return ret;
443+ enetsw_writel(priv, reg, ENETSW_MDIOC_REG);
444+ udelay(50);
445+ spin_unlock_bh(&priv->enetsw_mdio_lock);
446 }
447 
448-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
449+/*
450+ * enet sw PHY polling
451+ */
452+static void swphy_poll_timer(unsigned long data)
453 {
454- struct resource *res;
455- int i;
456+ struct bcm_enet_priv *priv = (struct bcm_enet_priv *)data;
457+ unsigned int i;
458 
459- for (i = 0; i < 3; i++) {
460- iounmap(bcm_enet_shared_base[i]);
461- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
462- release_mem_region(res->start, resource_size(res));
463+ for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
464+ struct bcm63xx_enetsw_port *port;
465+ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
466+ u8 override;
467+
468+ port = &priv->used_ports[i];
469+ if (!port->used)
470+ continue;
471+
472+ if (port->bypass_link)
473+ continue;
474+
475+ /* dummy read to clear */
476+ for (j = 0; j < 2; j++)
477+ val = bcmenet_sw_mdio_read(priv, port->external_phy,
478+ port->phy_id, MII_BMSR);
479+
480+ if (val == 0xffff)
481+ continue;
482+
483+ up = (val & BMSR_LSTATUS) ? 1 : 0;
484+ if (!(up ^ priv->sw_port_link[i]))
485+ continue;
486+
487+ priv->sw_port_link[i] = up;
488+
489+ /* link changed */
490+ if (!up) {
491+ dev_info(&priv->pdev->dev, "link DOWN on %s\n",
492+ port->name);
493+ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
494+ ENETSW_PORTOV_REG(i));
495+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
496+ ENETSW_PTCTRL_TXDIS_MASK,
497+ ENETSW_PTCTRL_REG(i));
498+ continue;
499+ }
500+
501+ advertise = bcmenet_sw_mdio_read(priv, port->external_phy,
502+ port->phy_id, MII_ADVERTISE);
503+
504+ lpa = bcmenet_sw_mdio_read(priv, port->external_phy,
505+ port->phy_id, MII_LPA);
506+
507+ lpa2 = bcmenet_sw_mdio_read(priv, port->external_phy,
508+ port->phy_id, MII_STAT1000);
509+
510+ /* figure out media and duplex from advertise and LPA values */
511+ media = mii_nway_result(lpa & advertise);
512+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
513+ if (lpa2 & LPA_1000FULL)
514+ duplex = 1;
515+
516+ if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
517+ speed = 1000;
518+ else {
519+ if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
520+ speed = 100;
521+ else
522+ speed = 10;
523+ }
524+
525+ dev_info(&priv->pdev->dev,
526+ "link UP on %s, %dMbps, %s-duplex\n",
527+ port->name, speed, duplex ? "full" : "half");
528+
529+ override = ENETSW_PORTOV_ENABLE_MASK |
530+ ENETSW_PORTOV_LINKUP_MASK;
531+
532+ if (speed == 1000)
533+ override |= ENETSW_IMPOV_1000_MASK;
534+ else if (speed == 100)
535+ override |= ENETSW_IMPOV_100_MASK;
536+ if (duplex)
537+ override |= ENETSW_IMPOV_FDX_MASK;
538+
539+ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
540+ enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i));
541     }
542- return 0;
543-}
544 
545-/*
546- * this "shared" driver is needed because both macs share a single
547- * address space
548- */
549-struct platform_driver bcm63xx_enet_shared_driver = {
550- .probe = bcm_enet_shared_probe,
551- .remove = __devexit_p(bcm_enet_shared_remove),
552- .driver = {
553- .name = "bcm63xx_enet_shared",
554- .owner = THIS_MODULE,
555- },
556-};
557+ priv->swphy_poll.expires = jiffies + HZ;
558+ add_timer(&priv->swphy_poll);
559+}
560 
561 /*
562- * entry point
563+ * open callback, allocate dma rings & buffers and start rx operation
564  */
565-static int __init bcm_enet_init(void)
566+static int bcm_enetsw_open(struct net_device *dev)
567 {
568- int ret;
569+ struct bcm_enet_priv *priv;
570+ struct device *kdev;
571+ int i, ret;
572+ unsigned int size;
573+ void *p;
574+ u32 val;
575 
576- ret = platform_driver_register(&bcm63xx_enet_shared_driver);
577+ priv = netdev_priv(dev);
578+ kdev = &priv->pdev->dev;
579+
580+ /* mask all interrupts and request them */
581+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
582+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
583+
584+ ret = request_irq(priv->irq_rx, bcm_enet_isr_dma,
585+ IRQF_DISABLED, dev->name, dev);
586     if (ret)
587- return ret;
588+ goto out_freeirq;
589 
590- ret = platform_driver_register(&bcm63xx_enet_driver);
591+ ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
592+ IRQF_DISABLED, dev->name, dev);
593     if (ret)
594- platform_driver_unregister(&bcm63xx_enet_shared_driver);
595+ goto out_freeirq_rx;
596+
597+ /* allocate rx dma ring */
598+ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
599+ p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
600+ if (!p) {
601+ dev_err(kdev, "cannot allocate rx ring %u\n", size);
602+ ret = -ENOMEM;
603+ goto out_freeirq_tx;
604+ }
605+
606+ memset(p, 0, size);
607+ priv->rx_desc_alloc_size = size;
608+ priv->rx_desc_cpu = p;
609+
610+ /* allocate tx dma ring */
611+ size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
612+ p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
613+ if (!p) {
614+ dev_err(kdev, "cannot allocate tx ring\n");
615+ ret = -ENOMEM;
616+ goto out_free_rx_ring;
617+ }
618+
619+ memset(p, 0, size);
620+ priv->tx_desc_alloc_size = size;
621+ priv->tx_desc_cpu = p;
622+
623+ priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size,
624+ GFP_KERNEL);
625+ if (!priv->tx_skb) {
626+ dev_err(kdev, "cannot allocate rx skb queue\n");
627+ ret = -ENOMEM;
628+ goto out_free_tx_ring;
629+ }
630+
631+ priv->tx_desc_count = priv->tx_ring_size;
632+ priv->tx_dirty_desc = 0;
633+ priv->tx_curr_desc = 0;
634+ spin_lock_init(&priv->tx_lock);
635+
636+ /* init & fill rx ring with skbs */
637+ priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size,
638+ GFP_KERNEL);
639+ if (!priv->rx_skb) {
640+ dev_err(kdev, "cannot allocate rx skb queue\n");
641+ ret = -ENOMEM;
642+ goto out_free_tx_skb;
643+ }
644+
645+ priv->rx_desc_count = 0;
646+ priv->rx_dirty_desc = 0;
647+ priv->rx_curr_desc = 0;
648+
649+ /* disable all ports */
650+ for (i = 0; i < 6; i++) {
651+ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
652+ ENETSW_PORTOV_REG(i));
653+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
654+ ENETSW_PTCTRL_TXDIS_MASK,
655+ ENETSW_PTCTRL_REG(i));
656+ }
657+
658+ /* reset mib */
659+ val = enetsw_readb(priv, ENETSW_GMCR_REG);
660+ val |= ENETSW_GMCR_RST_MIB_MASK;
661+ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
662+ mdelay(1);
663+ val &= ~ENETSW_GMCR_RST_MIB_MASK;
664+ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
665+ mdelay(1);
666+
667+ /* force CPU port state */
668+ val = enetsw_readb(priv, ENETSW_IMPOV_REG);
669+ val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
670+ enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
671+
672+ /* enable switch forward engine */
673+ val = enetsw_readb(priv, ENETSW_SWMODE_REG);
674+ val |= ENETSW_SWMODE_FWD_EN_MASK;
675+ enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
676+
677+ /* enable jumbo on all ports */
678+ enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
679+ enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
680+
681+ /* initialize flow control buffer allocation */
682+ enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
683+ ENETDMA_BUFALLOC_REG(priv->rx_chan));
684+
685+ if (bcm_enet_refill_rx(dev)) {
686+ dev_err(kdev, "cannot allocate rx skb queue\n");
687+ ret = -ENOMEM;
688+ goto out;
689+ }
690+
691+ /* write rx & tx ring addresses */
692+ enet_dmas_writel(priv, priv->rx_desc_dma,
693+ ENETDMAS_RSTART_REG(priv->rx_chan));
694+ enet_dmas_writel(priv, priv->tx_desc_dma,
695+ ENETDMAS_RSTART_REG(priv->tx_chan));
696+
697+ /* clear remaining state ram for rx & tx channel */
698+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
699+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
700+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
701+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
702+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
703+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
704+
705+ /* set dma maximum burst len */
706+ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
707+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
708+ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
709+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
710+
711+ /* set flow control low/high threshold to 1/3 / 2/3 */
712+ val = priv->rx_ring_size / 3;
713+ enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan));
714+ val = (priv->rx_ring_size * 2) / 3;
715+ enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan));
716+
717+ /* all set, enable mac and interrupts, start dma engine and
718+ * kick rx dma channel */
719+ wmb();
720+ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
721+ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
722+ ENETDMAC_CHANCFG_REG(priv->rx_chan));
723+
724+ /* watch "packet transferred" interrupt in rx and tx */
725+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
726+ ENETDMAC_IR_REG(priv->rx_chan));
727+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
728+ ENETDMAC_IR_REG(priv->tx_chan));
729+
730+ /* make sure we enable napi before rx interrupt */
731+ napi_enable(&priv->napi);
732+
733+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
734+ ENETDMAC_IRMASK_REG(priv->rx_chan));
735+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
736+ ENETDMAC_IRMASK_REG(priv->tx_chan));
737+
738+ netif_carrier_on(dev);
739+ netif_start_queue(dev);
740+
741+ /*
742+ * apply override config for bypass_link ports here.
743+ */
744+ for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
745+ struct bcm63xx_enetsw_port *port;
746+ u8 override;
747+ port = &priv->used_ports[i];
748+ if (!port->used)
749+ continue;
750+
751+ if (!port->bypass_link)
752+ continue;
753+
754+ override = ENETSW_PORTOV_ENABLE_MASK |
755+ ENETSW_PORTOV_LINKUP_MASK;
756+
757+ switch (port->force_speed) {
758+ case 1000:
759+ override |= ENETSW_IMPOV_1000_MASK;
760+ break;
761+ case 100:
762+ override |= ENETSW_IMPOV_100_MASK;
763+ break;
764+ case 10:
765+ break;
766+ default:
767+ printk(KERN_WARNING "invalid forced speed on port %s: "
768+ "assume 10\n",
769+ port->name);
770+ break;
771+ }
772+
773+ if (port->force_duplex_full)
774+ override = ENETSW_IMPOV_FDX_MASK;
775+
776+
777+ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
778+ enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i));
779+ }
780+
781+ /* start phy polling timer */
782+ init_timer(&priv->swphy_poll);
783+ priv->swphy_poll.function = swphy_poll_timer;
784+ priv->swphy_poll.data = (unsigned long)priv;
785+ priv->swphy_poll.expires = jiffies;
786+ add_timer(&priv->swphy_poll);
787+ return 0;
788+
789+out:
790+ for (i = 0; i < priv->rx_ring_size; i++) {
791+ struct bcm_enet_desc *desc;
792+
793+ if (!priv->rx_skb[i])
794+ continue;
795+
796+ desc = &priv->rx_desc_cpu[i];
797+ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
798+ DMA_FROM_DEVICE);
799+ kfree_skb(priv->rx_skb[i]);
800+ }
801+ kfree(priv->rx_skb);
802+
803+out_free_tx_skb:
804+ kfree(priv->tx_skb);
805+
806+out_free_tx_ring:
807+ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
808+ priv->tx_desc_cpu, priv->tx_desc_dma);
809+
810+out_free_rx_ring:
811+ dma_free_coherent(kdev, priv->rx_desc_alloc_size,
812+ priv->rx_desc_cpu, priv->rx_desc_dma);
813+
814+out_freeirq_tx:
815+ free_irq(priv->irq_tx, dev);
816+
817+out_freeirq_rx:
818+ free_irq(priv->irq_rx, dev);
819+
820+out_freeirq:
821+ return ret;
822+}
823+
824+/*
825+ * stop callback
826+ */
827+static int bcm_enetsw_stop(struct net_device *dev)
828+{
829+ struct bcm_enet_priv *priv;
830+ struct device *kdev;
831+ int i;
832+
833+ priv = netdev_priv(dev);
834+ kdev = &priv->pdev->dev;
835+
836+ del_timer_sync(&priv->swphy_poll);
837+ netif_stop_queue(dev);
838+ napi_disable(&priv->napi);
839+ del_timer_sync(&priv->rx_timeout);
840+
841+ /* mask all interrupts */
842+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
843+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
844+
845+ /* disable dma & mac */
846+ bcm_enet_disable_dma(priv, priv->tx_chan);
847+ bcm_enet_disable_dma(priv, priv->rx_chan);
848+
849+ /* force reclaim of all tx buffers */
850+ bcm_enet_tx_reclaim(dev, 1);
851+
852+ /* free the rx skb ring */
853+ for (i = 0; i < priv->rx_ring_size; i++) {
854+ struct bcm_enet_desc *desc;
855+
856+ if (!priv->rx_skb[i])
857+ continue;
858+
859+ desc = &priv->rx_desc_cpu[i];
860+ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
861+ DMA_FROM_DEVICE);
862+ kfree_skb(priv->rx_skb[i]);
863+ }
864+
865+ /* free remaining allocated memory */
866+ kfree(priv->rx_skb);
867+ kfree(priv->tx_skb);
868+ dma_free_coherent(kdev, priv->rx_desc_alloc_size,
869+ priv->rx_desc_cpu, priv->rx_desc_dma);
870+ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
871+ priv->tx_desc_cpu, priv->tx_desc_dma);
872+ free_irq(priv->irq_tx, dev);
873+ free_irq(priv->irq_rx, dev);
874+
875+ return 0;
876+}
877+
878+/*
879+ * try to sort out phy external status by walking the used_port field
880+ * in the bcm_enet_priv structure. in case the phy address is not
881+ * assigned to any physical port on the switch, assume it is external
882+ * (and yell at the user).
883+ */
884+static int bcm_enetsw_phy_is_external(struct bcm_enet_priv *priv, int phy_id)
885+{
886+ int i;
887+
888+ for (i = 0; i < (int)ARRAY_SIZE(priv->used_ports); ++i) {
889+ if (!priv->used_ports[i].used)
890+ continue;
891+ if (priv->used_ports[i].phy_id == phy_id)
892+ return priv->used_ports[i].external_phy;
893+ }
894+
895+ printk_once(KERN_WARNING "bcm63xx_enet: could not find a used port "
896+ "with phy_id %i, assuming phy is external\n", phy_id);
897+ return 1;
898+}
899+
900+/*
901+ * can't use bcmenet_sw_mdio_read directly as we need to sort out
902+ * external/internal status of the given phy_id first.
903+ */
904+static int bcm_enetsw_mii_mdio_read(struct net_device *dev, int phy_id,
905+ int location)
906+{
907+ struct bcm_enet_priv *priv;
908+
909+ priv = netdev_priv(dev);
910+ return bcmenet_sw_mdio_read(priv,
911+ bcm_enetsw_phy_is_external(priv, phy_id),
912+ phy_id, location);
913+}
914+
915+/*
916+ * can't use bcmenet_sw_mdio_write directly as we need to sort out
917+ * external/internal status of the given phy_id first.
918+ */
919+static void bcm_enetsw_mii_mdio_write(struct net_device *dev, int phy_id,
920+ int location,
921+ int val)
922+{
923+ struct bcm_enet_priv *priv;
924+
925+ priv = netdev_priv(dev);
926+ bcmenet_sw_mdio_write(priv, bcm_enetsw_phy_is_external(priv, phy_id),
927+ phy_id, location, val);
928+}
929+
930+static int bcm_enetsw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
931+{
932+ struct mii_if_info mii;
933+
934+ mii.dev = dev;
935+ mii.mdio_read = bcm_enetsw_mii_mdio_read;
936+ mii.mdio_write = bcm_enetsw_mii_mdio_write;
937+ mii.phy_id = 0;
938+ mii.phy_id_mask = 0x3f;
939+ mii.reg_num_mask = 0x1f;
940+ return generic_mii_ioctl(&mii, if_mii(rq), cmd, NULL);
941+
942+}
943+
944+static const struct net_device_ops bcm_enetsw_ops = {
945+ .ndo_open = bcm_enetsw_open,
946+ .ndo_stop = bcm_enetsw_stop,
947+ .ndo_start_xmit = bcm_enet_start_xmit,
948+ .ndo_change_mtu = bcm_enet_change_mtu,
949+ .ndo_do_ioctl = bcm_enetsw_ioctl,
950+};
951+
952+
953+static const struct bcm_enet_stats bcm_enetsw_gstrings_stats[] = {
954+ { "rx_packets", DEV_STAT(rx_packets), -1 },
955+ { "tx_packets", DEV_STAT(tx_packets), -1 },
956+ { "rx_bytes", DEV_STAT(rx_bytes), -1 },
957+ { "tx_bytes", DEV_STAT(tx_bytes), -1 },
958+ { "rx_errors", DEV_STAT(rx_errors), -1 },
959+ { "tx_errors", DEV_STAT(tx_errors), -1 },
960+ { "rx_dropped", DEV_STAT(rx_dropped), -1 },
961+ { "tx_dropped", DEV_STAT(tx_dropped), -1 },
962+
963+ { "tx_good_octets", GEN_STAT(mib.tx_gd_octets), ETHSW_MIB_RX_GD_OCT },
964+ { "tx_unicast", GEN_STAT(mib.tx_unicast), ETHSW_MIB_RX_BRDCAST },
965+ { "tx_broadcast", GEN_STAT(mib.tx_brdcast), ETHSW_MIB_RX_BRDCAST },
966+ { "tx_multicast", GEN_STAT(mib.tx_mult), ETHSW_MIB_RX_MULT },
967+ { "tx_64_octets", GEN_STAT(mib.tx_64), ETHSW_MIB_RX_64 },
968+ { "tx_65_127_oct", GEN_STAT(mib.tx_65_127), ETHSW_MIB_RX_65_127 },
969+ { "tx_128_255_oct", GEN_STAT(mib.tx_128_255), ETHSW_MIB_RX_128_255 },
970+ { "tx_256_511_oct", GEN_STAT(mib.tx_256_511), ETHSW_MIB_RX_256_511 },
971+ { "tx_512_1023_oct", GEN_STAT(mib.tx_512_1023), ETHSW_MIB_RX_512_1023},
972+ { "tx_1024_1522_oct", GEN_STAT(mib.tx_1024_max),
973+ ETHSW_MIB_RX_1024_1522 },
974+ { "tx_1523_2047_oct", GEN_STAT(mib.tx_1523_2047),
975+ ETHSW_MIB_RX_1523_2047 },
976+ { "tx_2048_4095_oct", GEN_STAT(mib.tx_2048_4095),
977+ ETHSW_MIB_RX_2048_4095 },
978+ { "tx_4096_8191_oct", GEN_STAT(mib.tx_4096_8191),
979+ ETHSW_MIB_RX_4096_8191 },
980+ { "tx_8192_9728_oct", GEN_STAT(mib.tx_8192_9728),
981+ ETHSW_MIB_RX_8192_9728 },
982+ { "tx_oversize", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR },
983+ { "tx_oversize_drop", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR_DISC },
984+ { "tx_dropped", GEN_STAT(mib.tx_drop), ETHSW_MIB_RX_DROP },
985+ { "tx_undersize", GEN_STAT(mib.tx_underrun), ETHSW_MIB_RX_UND },
986+ { "tx_pause", GEN_STAT(mib.tx_pause), ETHSW_MIB_RX_PAUSE },
987+
988+ { "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETHSW_MIB_TX_ALL_OCT },
989+ { "rx_broadcast", GEN_STAT(mib.rx_brdcast), ETHSW_MIB_TX_BRDCAST },
990+ { "rx_multicast", GEN_STAT(mib.rx_mult), ETHSW_MIB_TX_MULT },
991+ { "rx_unicast", GEN_STAT(mib.rx_unicast), ETHSW_MIB_TX_MULT },
992+ { "rx_pause", GEN_STAT(mib.rx_pause), ETHSW_MIB_TX_PAUSE },
993+ { "rx_dropped", GEN_STAT(mib.rx_drop), ETHSW_MIB_TX_DROP_PKTS },
994+
995+};
996+
997+#define BCM_ENETSW_STATS_LEN \
998+ (sizeof(bcm_enetsw_gstrings_stats) / sizeof(struct bcm_enet_stats))
999+
1000+static void bcm_enetsw_get_strings(struct net_device *netdev,
1001+ u32 stringset, u8 *data)
1002+{
1003+ int i;
1004+
1005+ switch (stringset) {
1006+ case ETH_SS_STATS:
1007+ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
1008+ memcpy(data + i * ETH_GSTRING_LEN,
1009+ bcm_enetsw_gstrings_stats[i].stat_string,
1010+ ETH_GSTRING_LEN);
1011+ }
1012+ break;
1013+ }
1014+}
1015+
1016+static int bcm_enetsw_get_sset_count(struct net_device *netdev,
1017+ int string_set)
1018+{
1019+ switch (string_set) {
1020+ case ETH_SS_STATS:
1021+ return BCM_ENETSW_STATS_LEN;
1022+ default:
1023+ return -EINVAL;
1024+ }
1025+}
1026+
1027+static void bcm_enetsw_get_drvinfo(struct net_device *netdev,
1028+ struct ethtool_drvinfo *drvinfo)
1029+{
1030+ strncpy(drvinfo->driver, bcm_enet_driver_name, 32);
1031+ strncpy(drvinfo->version, bcm_enet_driver_version, 32);
1032+ strncpy(drvinfo->fw_version, "N/A", 32);
1033+ strncpy(drvinfo->bus_info, "bcm63xx", 32);
1034+ drvinfo->n_stats = BCM_ENETSW_STATS_LEN;
1035+}
1036+
1037+static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev,
1038+ struct ethtool_stats *stats,
1039+ u64 *data)
1040+{
1041+ struct bcm_enet_priv *priv;
1042+ int i;
1043+
1044+ priv = netdev_priv(netdev);
1045+
1046+ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
1047+ const struct bcm_enet_stats *s;
1048+ u32 lo, hi;
1049+ char *p;
1050+ int reg;
1051+
1052+ s = &bcm_enetsw_gstrings_stats[i];
1053+
1054+ reg = s->mib_reg;
1055+ if (reg == -1)
1056+ continue;
1057+
1058+ lo = enetsw_readl(priv, ENETSW_MIB_REG(reg));
1059+ p = (char *)priv + s->stat_offset;
1060+
1061+ if (s->sizeof_stat == sizeof(u64)) {
1062+ hi = enetsw_readl(priv, ENETSW_MIB_REG(reg + 1));
1063+ *(u64 *)p = ((u64)hi << 32 | lo);
1064+ } else
1065+ *(u32 *)p = lo;
1066+ }
1067+
1068+ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
1069+ const struct bcm_enet_stats *s;
1070+ char *p;
1071+
1072+ s = &bcm_enetsw_gstrings_stats[i];
1073+
1074+ if (s->mib_reg == -1)
1075+ p = (char *)&netdev->stats + s->stat_offset;
1076+ else
1077+ p = (char *)priv + s->stat_offset;
1078+
1079+ data[i] = (s->sizeof_stat == sizeof(u64)) ?
1080+ *(u64 *)p : *(u32 *)p;
1081+ }
1082+}
1083+
1084+static void bcm_enetsw_get_ringparam(struct net_device *dev,
1085+ struct ethtool_ringparam *ering)
1086+{
1087+ struct bcm_enet_priv *priv;
1088+
1089+ priv = netdev_priv(dev);
1090+
1091+ /* rx/tx ring is actually only limited by memory */
1092+ ering->rx_max_pending = 8192;
1093+ ering->tx_max_pending = 8192;
1094+ ering->rx_mini_max_pending = 0;
1095+ ering->rx_jumbo_max_pending = 0;
1096+ ering->rx_pending = priv->rx_ring_size;
1097+ ering->tx_pending = priv->tx_ring_size;
1098+}
1099+
1100+static int bcm_enetsw_set_ringparam(struct net_device *dev,
1101+ struct ethtool_ringparam *ering)
1102+{
1103+ struct bcm_enet_priv *priv;
1104+ int was_running;
1105+
1106+ priv = netdev_priv(dev);
1107+
1108+ was_running = 0;
1109+ if (netif_running(dev)) {
1110+ bcm_enetsw_stop(dev);
1111+ was_running = 1;
1112+ }
1113+
1114+ priv->rx_ring_size = ering->rx_pending;
1115+ priv->tx_ring_size = ering->tx_pending;
1116+
1117+ if (was_running) {
1118+ int err;
1119+
1120+ err = bcm_enetsw_open(dev);
1121+ if (err)
1122+ dev_close(dev);
1123+ }
1124+ return 0;
1125+}
1126+
1127+static struct ethtool_ops bcm_enetsw_ethtool_ops = {
1128+ .get_strings = bcm_enetsw_get_strings,
1129+ .get_sset_count = bcm_enetsw_get_sset_count,
1130+ .get_ethtool_stats = bcm_enetsw_get_ethtool_stats,
1131+ .get_drvinfo = bcm_enetsw_get_drvinfo,
1132+ .get_ringparam = bcm_enetsw_get_ringparam,
1133+ .set_ringparam = bcm_enetsw_set_ringparam,
1134+};
1135+
1136+/*
1137+ * allocate netdevice, request register memory and register device.
1138+ */
1139+static int __devinit bcm_enetsw_probe(struct platform_device *pdev)
1140+{
1141+ struct bcm_enet_priv *priv;
1142+ struct net_device *dev;
1143+ struct bcm63xx_enetsw_platform_data *pd;
1144+ struct resource *res_mem;
1145+ int ret, irq_rx, irq_tx;
1146+
1147+ /* stop if shared driver failed, assume driver->probe will be
1148+ * called in the same order we register devices (correct ?) */
1149+ if (!bcm_enet_shared_base[0])
1150+ return -ENODEV;
1151+
1152+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1153+ irq_rx = platform_get_irq(pdev, 0);
1154+ irq_tx = platform_get_irq(pdev, 1);
1155+ if (!res_mem || irq_rx < 0 || irq_tx < 0)
1156+ return -ENODEV;
1157+
1158+ ret = 0;
1159+ dev = alloc_etherdev(sizeof(*priv));
1160+ if (!dev)
1161+ return -ENOMEM;
1162+ priv = netdev_priv(dev);
1163+ memset(priv, 0, sizeof(*priv));
1164+
1165+ /* initialize default and fetch platform data */
1166+ priv->irq_rx = irq_rx;
1167+ priv->irq_tx = irq_tx;
1168+ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
1169+ priv->tx_ring_size = BCMENET_DEF_TX_DESC;
1170+
1171+ pd = pdev->dev.platform_data;
1172+ if (pd) {
1173+ memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
1174+ memcpy(priv->used_ports, pd->used_ports,
1175+ sizeof (pd->used_ports));
1176+ }
1177+
1178+ ret = compute_hw_mtu(priv, dev->mtu);
1179+ if (ret)
1180+ goto out;
1181+
1182+ if (!request_mem_region(res_mem->start, resource_size(res_mem),
1183+ "bcm63xx_enetsw")) {
1184+ ret = -EBUSY;
1185+ goto out;
1186+ }
1187+
1188+ priv->base = ioremap(res_mem->start, resource_size(res_mem));
1189+ if (priv->base == NULL) {
1190+ ret = -ENOMEM;
1191+ goto out_release_mem;
1192+ }
1193+
1194+ priv->mac_clk = clk_get(&pdev->dev, "enetsw");
1195+ if (IS_ERR(priv->mac_clk)) {
1196+ ret = PTR_ERR(priv->mac_clk);
1197+ goto out_unmap;
1198+ }
1199+ clk_enable(priv->mac_clk);
1200+
1201+ priv->rx_chan = 0;
1202+ priv->tx_chan = 1;
1203+ spin_lock_init(&priv->rx_lock);
1204+
1205+ /* init rx timeout (used for oom) */
1206+ init_timer(&priv->rx_timeout);
1207+ priv->rx_timeout.function = bcm_enet_refill_rx_timer;
1208+ priv->rx_timeout.data = (unsigned long)dev;
1209+
1210+ /* register netdevice */
1211+ dev->netdev_ops = &bcm_enetsw_ops;
1212+ netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
1213+ SET_ETHTOOL_OPS(dev, &bcm_enetsw_ethtool_ops);
1214+ SET_NETDEV_DEV(dev, &pdev->dev);
1215+
1216+ spin_lock_init(&priv->enetsw_mdio_lock);
1217+
1218+ ret = register_netdev(dev);
1219+ if (ret)
1220+ goto out_put_clk;
1221+
1222+ netif_carrier_off(dev);
1223+ platform_set_drvdata(pdev, dev);
1224+ priv->pdev = pdev;
1225+ priv->net_dev = dev;
1226+
1227+ return 0;
1228+
1229+out_put_clk:
1230+ clk_put(priv->mac_clk);
1231+
1232+out_unmap:
1233+ iounmap(priv->base);
1234+
1235+out_release_mem:
1236+ release_mem_region(res_mem->start, resource_size(res_mem));
1237+out:
1238+ free_netdev(dev);
1239+ return ret;
1240+}
1241+
1242+
1243+/*
1244+ * exit func, stops hardware and unregisters netdevice
1245+ */
1246+static int __devexit bcm_enetsw_remove(struct platform_device *pdev)
1247+{
1248+ struct bcm_enet_priv *priv;
1249+ struct net_device *dev;
1250+ struct resource *res;
1251+
1252+ /* stop netdevice */
1253+ dev = platform_get_drvdata(pdev);
1254+ priv = netdev_priv(dev);
1255+ unregister_netdev(dev);
1256+
1257+ /* release device resources */
1258+ iounmap(priv->base);
1259+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1260+ release_mem_region(res->start, resource_size(res));
1261+
1262+ platform_set_drvdata(pdev, NULL);
1263+ free_netdev(dev);
1264+ return 0;
1265+}
1266+
1267+struct platform_driver bcm63xx_enetsw_driver = {
1268+ .probe = bcm_enetsw_probe,
1269+ .remove = __devexit_p(bcm_enetsw_remove),
1270+ .driver = {
1271+ .name = "bcm63xx_enetsw",
1272+ .owner = THIS_MODULE,
1273+ },
1274+};
1275+
1276+/*
1277+ * reserve & remap memory space shared between all macs
1278+ */
1279+static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
1280+{
1281+ struct resource *res;
1282+ int ret, i, requested[3];
1283+
1284+ memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base));
1285+ memset(requested, 0, sizeof (requested));
1286+
1287+ for (i = 0; i < 3; i++) {
1288+ void __iomem *p;
1289+
1290+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1291+ if (!res) {
1292+ ret = -EINVAL;
1293+ goto fail;
1294+ }
1295+
1296+ if (!request_mem_region(res->start, resource_size(res),
1297+ "bcm63xx_enet_dma")) {
1298+ ret = -EBUSY;
1299+ goto fail;
1300+ }
1301+ requested[i] = 0;
1302+
1303+ p = ioremap(res->start, resource_size(res));
1304+ if (!p) {
1305+ ret = -ENOMEM;
1306+ goto fail;
1307+ }
1308+
1309+ bcm_enet_shared_base[i] = p;
1310+ }
1311+
1312+ return 0;
1313+
1314+fail:
1315+ for (i = 0; i < 3; i++) {
1316+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1317+ if (!res)
1318+ continue;
1319+ if (bcm_enet_shared_base[i])
1320+ iounmap(bcm_enet_shared_base[i]);
1321+ if (requested[i])
1322+ release_mem_region(res->start, resource_size(res));
1323+ }
1324+ return ret;
1325+}
1326+
1327+static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
1328+{
1329+ struct resource *res;
1330+ int i;
1331+
1332+ for (i = 0; i < 3; i++) {
1333+ iounmap(bcm_enet_shared_base[i]);
1334+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1335+ release_mem_region(res->start, resource_size(res));
1336+ }
1337+ return 0;
1338+}
1339+
1340+/*
1341+ * this "shared" driver is needed because both macs share a single
1342+ * address space
1343+ */
1344+struct platform_driver bcm63xx_enet_shared_driver = {
1345+ .probe = bcm_enet_shared_probe,
1346+ .remove = __devexit_p(bcm_enet_shared_remove),
1347+ .driver = {
1348+ .name = "bcm63xx_enet_shared",
1349+ .owner = THIS_MODULE,
1350+ },
1351+};
1352+
1353+/*
1354+ * entry point
1355+ */
1356+static int __init bcm_enet_init(void)
1357+{
1358+ int ret;
1359+
1360+ ret = platform_driver_register(&bcm63xx_enet_shared_driver);
1361+ if (ret)
1362+ return ret;
1363+
1364+ ret = platform_driver_register(&bcm63xx_enet_driver);
1365+ if (ret)
1366+ platform_driver_unregister(&bcm63xx_enet_shared_driver);
1367+
1368+ ret = platform_driver_register(&bcm63xx_enetsw_driver);
1369+ if (ret) {
1370+ platform_driver_unregister(&bcm63xx_enet_driver);
1371+ platform_driver_unregister(&bcm63xx_enet_shared_driver);
1372+ }
1373 
1374     return ret;
1375 }
1376@@ -2018,6 +2937,7 @@ static int __init bcm_enet_init(void)
1377 static void __exit bcm_enet_exit(void)
1378 {
1379     platform_driver_unregister(&bcm63xx_enet_driver);
1380+ platform_driver_unregister(&bcm63xx_enetsw_driver);
1381     platform_driver_unregister(&bcm63xx_enet_shared_driver);
1382 }
1383 
1384--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
1385+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
1386@@ -112,11 +112,60 @@ struct bcm_enet_desc {
1387 #define ETH_MIB_RX_CNTRL 54
1388 
1389 
1390+/*
1391+ * SW MIB Counters register definitions
1392+*/
1393+#define ETHSW_MIB_TX_ALL_OCT 0
1394+#define ETHSW_MIB_TX_DROP_PKTS 2
1395+#define ETHSW_MIB_TX_QOS_PKTS 3
1396+#define ETHSW_MIB_TX_BRDCAST 4
1397+#define ETHSW_MIB_TX_MULT 5
1398+#define ETHSW_MIB_TX_UNI 6
1399+#define ETHSW_MIB_TX_COL 7
1400+#define ETHSW_MIB_TX_1_COL 8
1401+#define ETHSW_MIB_TX_M_COL 9
1402+#define ETHSW_MIB_TX_DEF 10
1403+#define ETHSW_MIB_TX_LATE 11
1404+#define ETHSW_MIB_TX_EX_COL 12
1405+#define ETHSW_MIB_TX_PAUSE 14
1406+#define ETHSW_MIB_TX_QOS_OCT 15
1407+
1408+#define ETHSW_MIB_RX_ALL_OCT 17
1409+#define ETHSW_MIB_RX_UND 19
1410+#define ETHSW_MIB_RX_PAUSE 20
1411+#define ETHSW_MIB_RX_64 21
1412+#define ETHSW_MIB_RX_65_127 22
1413+#define ETHSW_MIB_RX_128_255 23
1414+#define ETHSW_MIB_RX_256_511 24
1415+#define ETHSW_MIB_RX_512_1023 25
1416+#define ETHSW_MIB_RX_1024_1522 26
1417+#define ETHSW_MIB_RX_OVR 27
1418+#define ETHSW_MIB_RX_JAB 28
1419+#define ETHSW_MIB_RX_ALIGN 29
1420+#define ETHSW_MIB_RX_CRC 30
1421+#define ETHSW_MIB_RX_GD_OCT 31
1422+#define ETHSW_MIB_RX_DROP 33
1423+#define ETHSW_MIB_RX_UNI 34
1424+#define ETHSW_MIB_RX_MULT 35
1425+#define ETHSW_MIB_RX_BRDCAST 36
1426+#define ETHSW_MIB_RX_SA_CHANGE 37
1427+#define ETHSW_MIB_RX_FRAG 38
1428+#define ETHSW_MIB_RX_OVR_DISC 39
1429+#define ETHSW_MIB_RX_SYM 40
1430+#define ETHSW_MIB_RX_QOS_PKTS 41
1431+#define ETHSW_MIB_RX_QOS_OCT 42
1432+#define ETHSW_MIB_RX_1523_2047 44
1433+#define ETHSW_MIB_RX_2048_4095 45
1434+#define ETHSW_MIB_RX_4096_8191 46
1435+#define ETHSW_MIB_RX_8192_9728 47
1436+
1437+
1438 struct bcm_enet_mib_counters {
1439     u64 tx_gd_octets;
1440     u32 tx_gd_pkts;
1441     u32 tx_all_octets;
1442     u32 tx_all_pkts;
1443+ u32 tx_unicast;
1444     u32 tx_brdcast;
1445     u32 tx_mult;
1446     u32 tx_64;
1447@@ -125,7 +174,12 @@ struct bcm_enet_mib_counters {
1448     u32 tx_256_511;
1449     u32 tx_512_1023;
1450     u32 tx_1024_max;
1451+ u32 tx_1523_2047;
1452+ u32 tx_2048_4095;
1453+ u32 tx_4096_8191;
1454+ u32 tx_8192_9728;
1455     u32 tx_jab;
1456+ u32 tx_drop;
1457     u32 tx_ovr;
1458     u32 tx_frag;
1459     u32 tx_underrun;
1460@@ -142,6 +196,7 @@ struct bcm_enet_mib_counters {
1461     u32 rx_all_octets;
1462     u32 rx_all_pkts;
1463     u32 rx_brdcast;
1464+ u32 rx_unicast;
1465     u32 rx_mult;
1466     u32 rx_64;
1467     u32 rx_65_127;
1468@@ -297,6 +352,22 @@ struct bcm_enet_priv {
1469 
1470     /* maximum hardware transmit/receive size */
1471     unsigned int hw_mtu;
1472+
1473+ /* port mapping for switch devices */
1474+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
1475+ int sw_port_link[ENETSW_MAX_PORT];
1476+
1477+ /* used to poll switch port state */
1478+ struct timer_list swphy_poll;
1479+ spinlock_t enetsw_mdio_lock;
1480 };
1481 
1482+static inline int bcm_enet_is_sw(struct bcm_enet_priv *priv)
1483+{
1484+ if (BCMCPU_IS_6368())
1485+ return 1;
1486+ else
1487+ return 0;
1488+}
1489+
1490 #endif /* ! BCM63XX_ENET_H_ */
1491

Archive Download this file



interactive