xref: /openbmc/linux/drivers/net/ethernet/broadcom/bgmac.c (revision dd4544f05469aaaeee891d7dc54d66430344321e)
1*dd4544f0SRafał Miłecki /*
2*dd4544f0SRafał Miłecki  * Driver for (BCM4706)? GBit MAC core on BCMA bus.
3*dd4544f0SRafał Miłecki  *
4*dd4544f0SRafał Miłecki  * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
5*dd4544f0SRafał Miłecki  *
6*dd4544f0SRafał Miłecki  * Licensed under the GNU/GPL. See COPYING for details.
7*dd4544f0SRafał Miłecki  */
8*dd4544f0SRafał Miłecki 
9*dd4544f0SRafał Miłecki #include "bgmac.h"
10*dd4544f0SRafał Miłecki 
11*dd4544f0SRafał Miłecki #include <linux/kernel.h>
12*dd4544f0SRafał Miłecki #include <linux/module.h>
13*dd4544f0SRafał Miłecki #include <linux/delay.h>
14*dd4544f0SRafał Miłecki #include <linux/etherdevice.h>
15*dd4544f0SRafał Miłecki #include <linux/mii.h>
16*dd4544f0SRafał Miłecki #include <linux/interrupt.h>
17*dd4544f0SRafał Miłecki #include <linux/dma-mapping.h>
18*dd4544f0SRafał Miłecki #include <asm/mach-bcm47xx/nvram.h>
19*dd4544f0SRafał Miłecki 
20*dd4544f0SRafał Miłecki static const struct bcma_device_id bgmac_bcma_tbl[] = {
21*dd4544f0SRafał Miłecki 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
22*dd4544f0SRafał Miłecki 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
23*dd4544f0SRafał Miłecki 	BCMA_CORETABLE_END
24*dd4544f0SRafał Miłecki };
25*dd4544f0SRafał Miłecki MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
26*dd4544f0SRafał Miłecki 
27*dd4544f0SRafał Miłecki static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask,
28*dd4544f0SRafał Miłecki 			     u32 value, int timeout)
29*dd4544f0SRafał Miłecki {
30*dd4544f0SRafał Miłecki 	u32 val;
31*dd4544f0SRafał Miłecki 	int i;
32*dd4544f0SRafał Miłecki 
33*dd4544f0SRafał Miłecki 	for (i = 0; i < timeout / 10; i++) {
34*dd4544f0SRafał Miłecki 		val = bcma_read32(core, reg);
35*dd4544f0SRafał Miłecki 		if ((val & mask) == value)
36*dd4544f0SRafał Miłecki 			return true;
37*dd4544f0SRafał Miłecki 		udelay(10);
38*dd4544f0SRafał Miłecki 	}
39*dd4544f0SRafał Miłecki 	pr_err("Timeout waiting for reg 0x%X\n", reg);
40*dd4544f0SRafał Miłecki 	return false;
41*dd4544f0SRafał Miłecki }
42*dd4544f0SRafał Miłecki 
43*dd4544f0SRafał Miłecki /**************************************************
44*dd4544f0SRafał Miłecki  * DMA
45*dd4544f0SRafał Miłecki  **************************************************/
46*dd4544f0SRafał Miłecki 
47*dd4544f0SRafał Miłecki static void bgmac_dma_tx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
48*dd4544f0SRafał Miłecki {
49*dd4544f0SRafał Miłecki 	u32 val;
50*dd4544f0SRafał Miłecki 	int i;
51*dd4544f0SRafał Miłecki 
52*dd4544f0SRafał Miłecki 	if (!ring->mmio_base)
53*dd4544f0SRafał Miłecki 		return;
54*dd4544f0SRafał Miłecki 
55*dd4544f0SRafał Miłecki 	/* Suspend DMA TX ring first.
56*dd4544f0SRafał Miłecki 	 * bgmac_wait_value doesn't support waiting for any of few values, so
57*dd4544f0SRafał Miłecki 	 * implement whole loop here.
58*dd4544f0SRafał Miłecki 	 */
59*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL,
60*dd4544f0SRafał Miłecki 		    BGMAC_DMA_TX_SUSPEND);
61*dd4544f0SRafał Miłecki 	for (i = 0; i < 10000 / 10; i++) {
62*dd4544f0SRafał Miłecki 		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
63*dd4544f0SRafał Miłecki 		val &= BGMAC_DMA_TX_STAT;
64*dd4544f0SRafał Miłecki 		if (val == BGMAC_DMA_TX_STAT_DISABLED ||
65*dd4544f0SRafał Miłecki 		    val == BGMAC_DMA_TX_STAT_IDLEWAIT ||
66*dd4544f0SRafał Miłecki 		    val == BGMAC_DMA_TX_STAT_STOPPED) {
67*dd4544f0SRafał Miłecki 			i = 0;
68*dd4544f0SRafał Miłecki 			break;
69*dd4544f0SRafał Miłecki 		}
70*dd4544f0SRafał Miłecki 		udelay(10);
71*dd4544f0SRafał Miłecki 	}
72*dd4544f0SRafał Miłecki 	if (i)
73*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Timeout suspending DMA TX ring 0x%X (BGMAC_DMA_TX_STAT: 0x%08X)\n",
74*dd4544f0SRafał Miłecki 			  ring->mmio_base, val);
75*dd4544f0SRafał Miłecki 
76*dd4544f0SRafał Miłecki 	/* Remove SUSPEND bit */
77*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, 0);
78*dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(bgmac->core,
79*dd4544f0SRafał Miłecki 			      ring->mmio_base + BGMAC_DMA_TX_STATUS,
80*dd4544f0SRafał Miłecki 			      BGMAC_DMA_TX_STAT, BGMAC_DMA_TX_STAT_DISABLED,
81*dd4544f0SRafał Miłecki 			      10000)) {
82*dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "DMA TX ring 0x%X wasn't disabled on time, waiting additional 300us\n",
83*dd4544f0SRafał Miłecki 			   ring->mmio_base);
84*dd4544f0SRafał Miłecki 		udelay(300);
85*dd4544f0SRafał Miłecki 		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
86*dd4544f0SRafał Miłecki 		if ((val & BGMAC_DMA_TX_STAT) != BGMAC_DMA_TX_STAT_DISABLED)
87*dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Reset of DMA TX ring 0x%X failed\n",
88*dd4544f0SRafał Miłecki 				  ring->mmio_base);
89*dd4544f0SRafał Miłecki 	}
90*dd4544f0SRafał Miłecki }
91*dd4544f0SRafał Miłecki 
92*dd4544f0SRafał Miłecki static void bgmac_dma_tx_enable(struct bgmac *bgmac,
93*dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
94*dd4544f0SRafał Miłecki {
95*dd4544f0SRafał Miłecki 	u32 ctl;
96*dd4544f0SRafał Miłecki 
97*dd4544f0SRafał Miłecki 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
98*dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_TX_ENABLE;
99*dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
100*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
101*dd4544f0SRafał Miłecki }
102*dd4544f0SRafał Miłecki 
103*dd4544f0SRafał Miłecki static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
104*dd4544f0SRafał Miłecki 				    struct bgmac_dma_ring *ring,
105*dd4544f0SRafał Miłecki 				    struct sk_buff *skb)
106*dd4544f0SRafał Miłecki {
107*dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
108*dd4544f0SRafał Miłecki 	struct net_device *net_dev = bgmac->net_dev;
109*dd4544f0SRafał Miłecki 	struct bgmac_dma_desc *dma_desc;
110*dd4544f0SRafał Miłecki 	struct bgmac_slot_info *slot;
111*dd4544f0SRafał Miłecki 	u32 ctl0, ctl1;
112*dd4544f0SRafał Miłecki 	int free_slots;
113*dd4544f0SRafał Miłecki 
114*dd4544f0SRafał Miłecki 	if (skb->len > BGMAC_DESC_CTL1_LEN) {
115*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Too long skb (%d)\n", skb->len);
116*dd4544f0SRafał Miłecki 		goto err_stop_drop;
117*dd4544f0SRafał Miłecki 	}
118*dd4544f0SRafał Miłecki 
119*dd4544f0SRafał Miłecki 	if (ring->start <= ring->end)
120*dd4544f0SRafał Miłecki 		free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
121*dd4544f0SRafał Miłecki 	else
122*dd4544f0SRafał Miłecki 		free_slots = ring->start - ring->end;
123*dd4544f0SRafał Miłecki 	if (free_slots == 1) {
124*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
125*dd4544f0SRafał Miłecki 		netif_stop_queue(net_dev);
126*dd4544f0SRafał Miłecki 		return NETDEV_TX_BUSY;
127*dd4544f0SRafał Miłecki 	}
128*dd4544f0SRafał Miłecki 
129*dd4544f0SRafał Miłecki 	slot = &ring->slots[ring->end];
130*dd4544f0SRafał Miłecki 	slot->skb = skb;
131*dd4544f0SRafał Miłecki 	slot->dma_addr = dma_map_single(dma_dev, skb->data, skb->len,
132*dd4544f0SRafał Miłecki 					DMA_TO_DEVICE);
133*dd4544f0SRafał Miłecki 	if (dma_mapping_error(dma_dev, slot->dma_addr)) {
134*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Mapping error of skb on ring 0x%X\n",
135*dd4544f0SRafał Miłecki 			  ring->mmio_base);
136*dd4544f0SRafał Miłecki 		goto err_stop_drop;
137*dd4544f0SRafał Miłecki 	}
138*dd4544f0SRafał Miłecki 
139*dd4544f0SRafał Miłecki 	ctl0 = BGMAC_DESC_CTL0_IOC | BGMAC_DESC_CTL0_SOF | BGMAC_DESC_CTL0_EOF;
140*dd4544f0SRafał Miłecki 	if (ring->end == ring->num_slots - 1)
141*dd4544f0SRafał Miłecki 		ctl0 |= BGMAC_DESC_CTL0_EOT;
142*dd4544f0SRafał Miłecki 	ctl1 = skb->len & BGMAC_DESC_CTL1_LEN;
143*dd4544f0SRafał Miłecki 
144*dd4544f0SRafał Miłecki 	dma_desc = ring->cpu_base;
145*dd4544f0SRafał Miłecki 	dma_desc += ring->end;
146*dd4544f0SRafał Miłecki 	dma_desc->addr_low = cpu_to_le32(lower_32_bits(slot->dma_addr));
147*dd4544f0SRafał Miłecki 	dma_desc->addr_high = cpu_to_le32(upper_32_bits(slot->dma_addr));
148*dd4544f0SRafał Miłecki 	dma_desc->ctl0 = cpu_to_le32(ctl0);
149*dd4544f0SRafał Miłecki 	dma_desc->ctl1 = cpu_to_le32(ctl1);
150*dd4544f0SRafał Miłecki 
151*dd4544f0SRafał Miłecki 	wmb();
152*dd4544f0SRafał Miłecki 
153*dd4544f0SRafał Miłecki 	/* Increase ring->end to point empty slot. We tell hardware the first
154*dd4544f0SRafał Miłecki 	 * slot it should *not* read.
155*dd4544f0SRafał Miłecki 	 */
156*dd4544f0SRafał Miłecki 	if (++ring->end >= BGMAC_TX_RING_SLOTS)
157*dd4544f0SRafał Miłecki 		ring->end = 0;
158*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
159*dd4544f0SRafał Miłecki 		    ring->end * sizeof(struct bgmac_dma_desc));
160*dd4544f0SRafał Miłecki 
161*dd4544f0SRafał Miłecki 	/* Always keep one slot free to allow detecting bugged calls. */
162*dd4544f0SRafał Miłecki 	if (--free_slots == 1)
163*dd4544f0SRafał Miłecki 		netif_stop_queue(net_dev);
164*dd4544f0SRafał Miłecki 
165*dd4544f0SRafał Miłecki 	return NETDEV_TX_OK;
166*dd4544f0SRafał Miłecki 
167*dd4544f0SRafał Miłecki err_stop_drop:
168*dd4544f0SRafał Miłecki 	netif_stop_queue(net_dev);
169*dd4544f0SRafał Miłecki 	dev_kfree_skb(skb);
170*dd4544f0SRafał Miłecki 	return NETDEV_TX_OK;
171*dd4544f0SRafał Miłecki }
172*dd4544f0SRafał Miłecki 
173*dd4544f0SRafał Miłecki /* Free transmitted packets */
174*dd4544f0SRafał Miłecki static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
175*dd4544f0SRafał Miłecki {
176*dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
177*dd4544f0SRafał Miłecki 	int empty_slot;
178*dd4544f0SRafał Miłecki 	bool freed = false;
179*dd4544f0SRafał Miłecki 
180*dd4544f0SRafał Miłecki 	/* The last slot that hardware didn't consume yet */
181*dd4544f0SRafał Miłecki 	empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
182*dd4544f0SRafał Miłecki 	empty_slot &= BGMAC_DMA_TX_STATDPTR;
183*dd4544f0SRafał Miłecki 	empty_slot /= sizeof(struct bgmac_dma_desc);
184*dd4544f0SRafał Miłecki 
185*dd4544f0SRafał Miłecki 	while (ring->start != empty_slot) {
186*dd4544f0SRafał Miłecki 		struct bgmac_slot_info *slot = &ring->slots[ring->start];
187*dd4544f0SRafał Miłecki 
188*dd4544f0SRafał Miłecki 		if (slot->skb) {
189*dd4544f0SRafał Miłecki 			/* Unmap no longer used buffer */
190*dd4544f0SRafał Miłecki 			dma_unmap_single(dma_dev, slot->dma_addr,
191*dd4544f0SRafał Miłecki 					 slot->skb->len, DMA_TO_DEVICE);
192*dd4544f0SRafał Miłecki 			slot->dma_addr = 0;
193*dd4544f0SRafał Miłecki 
194*dd4544f0SRafał Miłecki 			/* Free memory! :) */
195*dd4544f0SRafał Miłecki 			dev_kfree_skb(slot->skb);
196*dd4544f0SRafał Miłecki 			slot->skb = NULL;
197*dd4544f0SRafał Miłecki 		} else {
198*dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
199*dd4544f0SRafał Miłecki 				  ring->start, ring->end);
200*dd4544f0SRafał Miłecki 		}
201*dd4544f0SRafał Miłecki 
202*dd4544f0SRafał Miłecki 		if (++ring->start >= BGMAC_TX_RING_SLOTS)
203*dd4544f0SRafał Miłecki 			ring->start = 0;
204*dd4544f0SRafał Miłecki 		freed = true;
205*dd4544f0SRafał Miłecki 	}
206*dd4544f0SRafał Miłecki 
207*dd4544f0SRafał Miłecki 	if (freed && netif_queue_stopped(bgmac->net_dev))
208*dd4544f0SRafał Miłecki 		netif_wake_queue(bgmac->net_dev);
209*dd4544f0SRafał Miłecki }
210*dd4544f0SRafał Miłecki 
211*dd4544f0SRafał Miłecki static void bgmac_dma_rx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
212*dd4544f0SRafał Miłecki {
213*dd4544f0SRafał Miłecki 	if (!ring->mmio_base)
214*dd4544f0SRafał Miłecki 		return;
215*dd4544f0SRafał Miłecki 
216*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, 0);
217*dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(bgmac->core,
218*dd4544f0SRafał Miłecki 			      ring->mmio_base + BGMAC_DMA_RX_STATUS,
219*dd4544f0SRafał Miłecki 			      BGMAC_DMA_RX_STAT, BGMAC_DMA_RX_STAT_DISABLED,
220*dd4544f0SRafał Miłecki 			      10000))
221*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Reset of ring 0x%X RX failed\n",
222*dd4544f0SRafał Miłecki 			  ring->mmio_base);
223*dd4544f0SRafał Miłecki }
224*dd4544f0SRafał Miłecki 
225*dd4544f0SRafał Miłecki static void bgmac_dma_rx_enable(struct bgmac *bgmac,
226*dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
227*dd4544f0SRafał Miłecki {
228*dd4544f0SRafał Miłecki 	u32 ctl;
229*dd4544f0SRafał Miłecki 
230*dd4544f0SRafał Miłecki 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL);
231*dd4544f0SRafał Miłecki 	ctl &= BGMAC_DMA_RX_ADDREXT_MASK;
232*dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_ENABLE;
233*dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
234*dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
235*dd4544f0SRafał Miłecki 	ctl |= BGMAC_RX_FRAME_OFFSET << BGMAC_DMA_RX_FRAME_OFFSET_SHIFT;
236*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, ctl);
237*dd4544f0SRafał Miłecki }
238*dd4544f0SRafał Miłecki 
239*dd4544f0SRafał Miłecki static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
240*dd4544f0SRafał Miłecki 				     struct bgmac_slot_info *slot)
241*dd4544f0SRafał Miłecki {
242*dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
243*dd4544f0SRafał Miłecki 	struct bgmac_rx_header *rx;
244*dd4544f0SRafał Miłecki 
245*dd4544f0SRafał Miłecki 	/* Alloc skb */
246*dd4544f0SRafał Miłecki 	slot->skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
247*dd4544f0SRafał Miłecki 	if (!slot->skb) {
248*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Allocation of skb failed!\n");
249*dd4544f0SRafał Miłecki 		return -ENOMEM;
250*dd4544f0SRafał Miłecki 	}
251*dd4544f0SRafał Miłecki 
252*dd4544f0SRafał Miłecki 	/* Poison - if everything goes fine, hardware will overwrite it */
253*dd4544f0SRafał Miłecki 	rx = (struct bgmac_rx_header *)slot->skb->data;
254*dd4544f0SRafał Miłecki 	rx->len = cpu_to_le16(0xdead);
255*dd4544f0SRafał Miłecki 	rx->flags = cpu_to_le16(0xbeef);
256*dd4544f0SRafał Miłecki 
257*dd4544f0SRafał Miłecki 	/* Map skb for the DMA */
258*dd4544f0SRafał Miłecki 	slot->dma_addr = dma_map_single(dma_dev, slot->skb->data,
259*dd4544f0SRafał Miłecki 					BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
260*dd4544f0SRafał Miłecki 	if (dma_mapping_error(dma_dev, slot->dma_addr)) {
261*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "DMA mapping error\n");
262*dd4544f0SRafał Miłecki 		return -ENOMEM;
263*dd4544f0SRafał Miłecki 	}
264*dd4544f0SRafał Miłecki 	if (slot->dma_addr & 0xC0000000)
265*dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
266*dd4544f0SRafał Miłecki 
267*dd4544f0SRafał Miłecki 	return 0;
268*dd4544f0SRafał Miłecki }
269*dd4544f0SRafał Miłecki 
270*dd4544f0SRafał Miłecki static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
271*dd4544f0SRafał Miłecki 			     int weight)
272*dd4544f0SRafał Miłecki {
273*dd4544f0SRafał Miłecki 	u32 end_slot;
274*dd4544f0SRafał Miłecki 	int handled = 0;
275*dd4544f0SRafał Miłecki 
276*dd4544f0SRafał Miłecki 	end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS);
277*dd4544f0SRafał Miłecki 	end_slot &= BGMAC_DMA_RX_STATDPTR;
278*dd4544f0SRafał Miłecki 	end_slot /= sizeof(struct bgmac_dma_desc);
279*dd4544f0SRafał Miłecki 
280*dd4544f0SRafał Miłecki 	ring->end = end_slot;
281*dd4544f0SRafał Miłecki 
282*dd4544f0SRafał Miłecki 	while (ring->start != ring->end) {
283*dd4544f0SRafał Miłecki 		struct device *dma_dev = bgmac->core->dma_dev;
284*dd4544f0SRafał Miłecki 		struct bgmac_slot_info *slot = &ring->slots[ring->start];
285*dd4544f0SRafał Miłecki 		struct sk_buff *skb = slot->skb;
286*dd4544f0SRafał Miłecki 		struct sk_buff *new_skb;
287*dd4544f0SRafał Miłecki 		struct bgmac_rx_header *rx;
288*dd4544f0SRafał Miłecki 		u16 len, flags;
289*dd4544f0SRafał Miłecki 
290*dd4544f0SRafał Miłecki 		/* Unmap buffer to make it accessible to the CPU */
291*dd4544f0SRafał Miłecki 		dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
292*dd4544f0SRafał Miłecki 					BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
293*dd4544f0SRafał Miłecki 
294*dd4544f0SRafał Miłecki 		/* Get info from the header */
295*dd4544f0SRafał Miłecki 		rx = (struct bgmac_rx_header *)skb->data;
296*dd4544f0SRafał Miłecki 		len = le16_to_cpu(rx->len);
297*dd4544f0SRafał Miłecki 		flags = le16_to_cpu(rx->flags);
298*dd4544f0SRafał Miłecki 
299*dd4544f0SRafał Miłecki 		/* Check for poison and drop or pass the packet */
300*dd4544f0SRafał Miłecki 		if (len == 0xdead && flags == 0xbeef) {
301*dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
302*dd4544f0SRafał Miłecki 				  ring->start);
303*dd4544f0SRafał Miłecki 		} else {
304*dd4544f0SRafał Miłecki 			new_skb = netdev_alloc_skb(bgmac->net_dev, len);
305*dd4544f0SRafał Miłecki 			if (new_skb) {
306*dd4544f0SRafał Miłecki 				skb_put(new_skb, len);
307*dd4544f0SRafał Miłecki 				skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET,
308*dd4544f0SRafał Miłecki 								 new_skb->data,
309*dd4544f0SRafał Miłecki 								 len);
310*dd4544f0SRafał Miłecki 				new_skb->protocol =
311*dd4544f0SRafał Miłecki 					eth_type_trans(new_skb, bgmac->net_dev);
312*dd4544f0SRafał Miłecki 				netif_receive_skb(new_skb);
313*dd4544f0SRafał Miłecki 				handled++;
314*dd4544f0SRafał Miłecki 			} else {
315*dd4544f0SRafał Miłecki 				bgmac->net_dev->stats.rx_dropped++;
316*dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Allocation of skb for copying packet failed!\n");
317*dd4544f0SRafał Miłecki 			}
318*dd4544f0SRafał Miłecki 
319*dd4544f0SRafał Miłecki 			/* Poison the old skb */
320*dd4544f0SRafał Miłecki 			rx->len = cpu_to_le16(0xdead);
321*dd4544f0SRafał Miłecki 			rx->flags = cpu_to_le16(0xbeef);
322*dd4544f0SRafał Miłecki 		}
323*dd4544f0SRafał Miłecki 
324*dd4544f0SRafał Miłecki 		/* Make it back accessible to the hardware */
325*dd4544f0SRafał Miłecki 		dma_sync_single_for_device(dma_dev, slot->dma_addr,
326*dd4544f0SRafał Miłecki 					   BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
327*dd4544f0SRafał Miłecki 
328*dd4544f0SRafał Miłecki 		if (++ring->start >= BGMAC_RX_RING_SLOTS)
329*dd4544f0SRafał Miłecki 			ring->start = 0;
330*dd4544f0SRafał Miłecki 
331*dd4544f0SRafał Miłecki 		if (handled >= weight) /* Should never be greater */
332*dd4544f0SRafał Miłecki 			break;
333*dd4544f0SRafał Miłecki 	}
334*dd4544f0SRafał Miłecki 
335*dd4544f0SRafał Miłecki 	return handled;
336*dd4544f0SRafał Miłecki }
337*dd4544f0SRafał Miłecki 
338*dd4544f0SRafał Miłecki /* Does ring support unaligned addressing? */
339*dd4544f0SRafał Miłecki static bool bgmac_dma_unaligned(struct bgmac *bgmac,
340*dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring,
341*dd4544f0SRafał Miłecki 				enum bgmac_dma_ring_type ring_type)
342*dd4544f0SRafał Miłecki {
343*dd4544f0SRafał Miłecki 	switch (ring_type) {
344*dd4544f0SRafał Miłecki 	case BGMAC_DMA_RING_TX:
345*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
346*dd4544f0SRafał Miłecki 			    0xff0);
347*dd4544f0SRafał Miłecki 		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO))
348*dd4544f0SRafał Miłecki 			return true;
349*dd4544f0SRafał Miłecki 		break;
350*dd4544f0SRafał Miłecki 	case BGMAC_DMA_RING_RX:
351*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
352*dd4544f0SRafał Miłecki 			    0xff0);
353*dd4544f0SRafał Miłecki 		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO))
354*dd4544f0SRafał Miłecki 			return true;
355*dd4544f0SRafał Miłecki 		break;
356*dd4544f0SRafał Miłecki 	}
357*dd4544f0SRafał Miłecki 	return false;
358*dd4544f0SRafał Miłecki }
359*dd4544f0SRafał Miłecki 
360*dd4544f0SRafał Miłecki static void bgmac_dma_ring_free(struct bgmac *bgmac,
361*dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
362*dd4544f0SRafał Miłecki {
363*dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
364*dd4544f0SRafał Miłecki 	struct bgmac_slot_info *slot;
365*dd4544f0SRafał Miłecki 	int size;
366*dd4544f0SRafał Miłecki 	int i;
367*dd4544f0SRafał Miłecki 
368*dd4544f0SRafał Miłecki 	for (i = 0; i < ring->num_slots; i++) {
369*dd4544f0SRafał Miłecki 		slot = &ring->slots[i];
370*dd4544f0SRafał Miłecki 		if (slot->skb) {
371*dd4544f0SRafał Miłecki 			if (slot->dma_addr)
372*dd4544f0SRafał Miłecki 				dma_unmap_single(dma_dev, slot->dma_addr,
373*dd4544f0SRafał Miłecki 						 slot->skb->len, DMA_TO_DEVICE);
374*dd4544f0SRafał Miłecki 			dev_kfree_skb(slot->skb);
375*dd4544f0SRafał Miłecki 		}
376*dd4544f0SRafał Miłecki 	}
377*dd4544f0SRafał Miłecki 
378*dd4544f0SRafał Miłecki 	if (ring->cpu_base) {
379*dd4544f0SRafał Miłecki 		/* Free ring of descriptors */
380*dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
381*dd4544f0SRafał Miłecki 		dma_free_coherent(dma_dev, size, ring->cpu_base,
382*dd4544f0SRafał Miłecki 				  ring->dma_base);
383*dd4544f0SRafał Miłecki 	}
384*dd4544f0SRafał Miłecki }
385*dd4544f0SRafał Miłecki 
386*dd4544f0SRafał Miłecki static void bgmac_dma_free(struct bgmac *bgmac)
387*dd4544f0SRafał Miłecki {
388*dd4544f0SRafał Miłecki 	int i;
389*dd4544f0SRafał Miłecki 
390*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
391*dd4544f0SRafał Miłecki 		bgmac_dma_ring_free(bgmac, &bgmac->tx_ring[i]);
392*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
393*dd4544f0SRafał Miłecki 		bgmac_dma_ring_free(bgmac, &bgmac->rx_ring[i]);
394*dd4544f0SRafał Miłecki }
395*dd4544f0SRafał Miłecki 
396*dd4544f0SRafał Miłecki static int bgmac_dma_alloc(struct bgmac *bgmac)
397*dd4544f0SRafał Miłecki {
398*dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
399*dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
400*dd4544f0SRafał Miłecki 	static const u16 ring_base[] = { BGMAC_DMA_BASE0, BGMAC_DMA_BASE1,
401*dd4544f0SRafał Miłecki 					 BGMAC_DMA_BASE2, BGMAC_DMA_BASE3, };
402*dd4544f0SRafał Miłecki 	int size; /* ring size: different for Tx and Rx */
403*dd4544f0SRafał Miłecki 	int err;
404*dd4544f0SRafał Miłecki 	int i;
405*dd4544f0SRafał Miłecki 
406*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base));
407*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base));
408*dd4544f0SRafał Miłecki 
409*dd4544f0SRafał Miłecki 	if (!(bcma_aread32(bgmac->core, BCMA_IOST) & BCMA_IOST_DMA64)) {
410*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Core does not report 64-bit DMA\n");
411*dd4544f0SRafał Miłecki 		return -ENOTSUPP;
412*dd4544f0SRafał Miłecki 	}
413*dd4544f0SRafał Miłecki 
414*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
415*dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[i];
416*dd4544f0SRafał Miłecki 		ring->num_slots = BGMAC_TX_RING_SLOTS;
417*dd4544f0SRafał Miłecki 		ring->mmio_base = ring_base[i];
418*dd4544f0SRafał Miłecki 		if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX))
419*dd4544f0SRafał Miłecki 			bgmac_warn(bgmac, "TX on ring 0x%X supports unaligned addressing but this feature is not implemented\n",
420*dd4544f0SRafał Miłecki 				   ring->mmio_base);
421*dd4544f0SRafał Miłecki 
422*dd4544f0SRafał Miłecki 		/* Alloc ring of descriptors */
423*dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
424*dd4544f0SRafał Miłecki 		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
425*dd4544f0SRafał Miłecki 						     &ring->dma_base,
426*dd4544f0SRafał Miłecki 						     GFP_KERNEL);
427*dd4544f0SRafał Miłecki 		if (!ring->cpu_base) {
428*dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Allocation of TX ring 0x%X failed\n",
429*dd4544f0SRafał Miłecki 				  ring->mmio_base);
430*dd4544f0SRafał Miłecki 			goto err_dma_free;
431*dd4544f0SRafał Miłecki 		}
432*dd4544f0SRafał Miłecki 		if (ring->dma_base & 0xC0000000)
433*dd4544f0SRafał Miłecki 			bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
434*dd4544f0SRafał Miłecki 
435*dd4544f0SRafał Miłecki 		/* No need to alloc TX slots yet */
436*dd4544f0SRafał Miłecki 	}
437*dd4544f0SRafał Miłecki 
438*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
439*dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[i];
440*dd4544f0SRafał Miłecki 		ring->num_slots = BGMAC_RX_RING_SLOTS;
441*dd4544f0SRafał Miłecki 		ring->mmio_base = ring_base[i];
442*dd4544f0SRafał Miłecki 		if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX))
443*dd4544f0SRafał Miłecki 			bgmac_warn(bgmac, "RX on ring 0x%X supports unaligned addressing but this feature is not implemented\n",
444*dd4544f0SRafał Miłecki 				   ring->mmio_base);
445*dd4544f0SRafał Miłecki 
446*dd4544f0SRafał Miłecki 		/* Alloc ring of descriptors */
447*dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
448*dd4544f0SRafał Miłecki 		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
449*dd4544f0SRafał Miłecki 						     &ring->dma_base,
450*dd4544f0SRafał Miłecki 						     GFP_KERNEL);
451*dd4544f0SRafał Miłecki 		if (!ring->cpu_base) {
452*dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Allocation of RX ring 0x%X failed\n",
453*dd4544f0SRafał Miłecki 				  ring->mmio_base);
454*dd4544f0SRafał Miłecki 			err = -ENOMEM;
455*dd4544f0SRafał Miłecki 			goto err_dma_free;
456*dd4544f0SRafał Miłecki 		}
457*dd4544f0SRafał Miłecki 		if (ring->dma_base & 0xC0000000)
458*dd4544f0SRafał Miłecki 			bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
459*dd4544f0SRafał Miłecki 
460*dd4544f0SRafał Miłecki 		/* Alloc RX slots */
461*dd4544f0SRafał Miłecki 		for (i = 0; i < ring->num_slots; i++) {
462*dd4544f0SRafał Miłecki 			err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[i]);
463*dd4544f0SRafał Miłecki 			if (err) {
464*dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Can't allocate skb for slot in RX ring\n");
465*dd4544f0SRafał Miłecki 				goto err_dma_free;
466*dd4544f0SRafał Miłecki 			}
467*dd4544f0SRafał Miłecki 		}
468*dd4544f0SRafał Miłecki 	}
469*dd4544f0SRafał Miłecki 
470*dd4544f0SRafał Miłecki 	return 0;
471*dd4544f0SRafał Miłecki 
472*dd4544f0SRafał Miłecki err_dma_free:
473*dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
474*dd4544f0SRafał Miłecki 	return -ENOMEM;
475*dd4544f0SRafał Miłecki }
476*dd4544f0SRafał Miłecki 
477*dd4544f0SRafał Miłecki static void bgmac_dma_init(struct bgmac *bgmac)
478*dd4544f0SRafał Miłecki {
479*dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
480*dd4544f0SRafał Miłecki 	struct bgmac_dma_desc *dma_desc;
481*dd4544f0SRafał Miłecki 	u32 ctl0, ctl1;
482*dd4544f0SRafał Miłecki 	int i;
483*dd4544f0SRafał Miłecki 
484*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
485*dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[i];
486*dd4544f0SRafał Miłecki 
487*dd4544f0SRafał Miłecki 		/* We don't implement unaligned addressing, so enable first */
488*dd4544f0SRafał Miłecki 		bgmac_dma_tx_enable(bgmac, ring);
489*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
490*dd4544f0SRafał Miłecki 			    lower_32_bits(ring->dma_base));
491*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI,
492*dd4544f0SRafał Miłecki 			    upper_32_bits(ring->dma_base));
493*dd4544f0SRafał Miłecki 
494*dd4544f0SRafał Miłecki 		ring->start = 0;
495*dd4544f0SRafał Miłecki 		ring->end = 0;	/* Points the slot that should *not* be read */
496*dd4544f0SRafał Miłecki 	}
497*dd4544f0SRafał Miłecki 
498*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
499*dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[i];
500*dd4544f0SRafał Miłecki 
501*dd4544f0SRafał Miłecki 		/* We don't implement unaligned addressing, so enable first */
502*dd4544f0SRafał Miłecki 		bgmac_dma_rx_enable(bgmac, ring);
503*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
504*dd4544f0SRafał Miłecki 			    lower_32_bits(ring->dma_base));
505*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI,
506*dd4544f0SRafał Miłecki 			    upper_32_bits(ring->dma_base));
507*dd4544f0SRafał Miłecki 
508*dd4544f0SRafał Miłecki 		for (i = 0, dma_desc = ring->cpu_base; i < ring->num_slots;
509*dd4544f0SRafał Miłecki 		     i++, dma_desc++) {
510*dd4544f0SRafał Miłecki 			ctl0 = ctl1 = 0;
511*dd4544f0SRafał Miłecki 
512*dd4544f0SRafał Miłecki 			if (i == ring->num_slots - 1)
513*dd4544f0SRafał Miłecki 				ctl0 |= BGMAC_DESC_CTL0_EOT;
514*dd4544f0SRafał Miłecki 			ctl1 |= BGMAC_RX_BUF_SIZE & BGMAC_DESC_CTL1_LEN;
515*dd4544f0SRafał Miłecki 			/* Is there any BGMAC device that requires extension? */
516*dd4544f0SRafał Miłecki 			/* ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT) &
517*dd4544f0SRafał Miłecki 			 * B43_DMA64_DCTL1_ADDREXT_MASK;
518*dd4544f0SRafał Miłecki 			 */
519*dd4544f0SRafał Miłecki 
520*dd4544f0SRafał Miłecki 			dma_desc->addr_low = cpu_to_le32(lower_32_bits(ring->slots[i].dma_addr));
521*dd4544f0SRafał Miłecki 			dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[i].dma_addr));
522*dd4544f0SRafał Miłecki 			dma_desc->ctl0 = cpu_to_le32(ctl0);
523*dd4544f0SRafał Miłecki 			dma_desc->ctl1 = cpu_to_le32(ctl1);
524*dd4544f0SRafał Miłecki 		}
525*dd4544f0SRafał Miłecki 
526*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
527*dd4544f0SRafał Miłecki 			    ring->num_slots * sizeof(struct bgmac_dma_desc));
528*dd4544f0SRafał Miłecki 
529*dd4544f0SRafał Miłecki 		ring->start = 0;
530*dd4544f0SRafał Miłecki 		ring->end = 0;
531*dd4544f0SRafał Miłecki 	}
532*dd4544f0SRafał Miłecki }
533*dd4544f0SRafał Miłecki 
534*dd4544f0SRafał Miłecki /**************************************************
535*dd4544f0SRafał Miłecki  * PHY ops
536*dd4544f0SRafał Miłecki  **************************************************/
537*dd4544f0SRafał Miłecki 
538*dd4544f0SRafał Miłecki u16 bgmac_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg)
539*dd4544f0SRafał Miłecki {
540*dd4544f0SRafał Miłecki 	struct bcma_device *core;
541*dd4544f0SRafał Miłecki 	u16 phy_access_addr;
542*dd4544f0SRafał Miłecki 	u16 phy_ctl_addr;
543*dd4544f0SRafał Miłecki 	u32 tmp;
544*dd4544f0SRafał Miłecki 
545*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK);
546*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK);
547*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT);
548*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK);
549*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT);
550*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE);
551*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START);
552*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK);
553*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK);
554*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
555*dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);
556*dd4544f0SRafał Miłecki 
557*dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
558*dd4544f0SRafał Miłecki 		core = bgmac->core->bus->drv_gmac_cmn.core;
559*dd4544f0SRafał Miłecki 		phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
560*dd4544f0SRafał Miłecki 		phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
561*dd4544f0SRafał Miłecki 	} else {
562*dd4544f0SRafał Miłecki 		core = bgmac->core;
563*dd4544f0SRafał Miłecki 		phy_access_addr = BGMAC_PHY_ACCESS;
564*dd4544f0SRafał Miłecki 		phy_ctl_addr = BGMAC_PHY_CNTL;
565*dd4544f0SRafał Miłecki 	}
566*dd4544f0SRafał Miłecki 
567*dd4544f0SRafał Miłecki 	tmp = bcma_read32(core, phy_ctl_addr);
568*dd4544f0SRafał Miłecki 	tmp &= ~BGMAC_PC_EPA_MASK;
569*dd4544f0SRafał Miłecki 	tmp |= phyaddr;
570*dd4544f0SRafał Miłecki 	bcma_write32(core, phy_ctl_addr, tmp);
571*dd4544f0SRafał Miłecki 
572*dd4544f0SRafał Miłecki 	tmp = BGMAC_PA_START;
573*dd4544f0SRafał Miłecki 	tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
574*dd4544f0SRafał Miłecki 	tmp |= reg << BGMAC_PA_REG_SHIFT;
575*dd4544f0SRafał Miłecki 	bcma_write32(core, phy_access_addr, tmp);
576*dd4544f0SRafał Miłecki 
577*dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) {
578*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Reading PHY %d register 0x%X failed\n",
579*dd4544f0SRafał Miłecki 			  phyaddr, reg);
580*dd4544f0SRafał Miłecki 		return 0xffff;
581*dd4544f0SRafał Miłecki 	}
582*dd4544f0SRafał Miłecki 
583*dd4544f0SRafał Miłecki 	return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK;
584*dd4544f0SRafał Miłecki }
585*dd4544f0SRafał Miłecki 
586*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
587*dd4544f0SRafał Miłecki void bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value)
588*dd4544f0SRafał Miłecki {
589*dd4544f0SRafał Miłecki 	struct bcma_device *core;
590*dd4544f0SRafał Miłecki 	u16 phy_access_addr;
591*dd4544f0SRafał Miłecki 	u16 phy_ctl_addr;
592*dd4544f0SRafał Miłecki 	u32 tmp;
593*dd4544f0SRafał Miłecki 
594*dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
595*dd4544f0SRafał Miłecki 		core = bgmac->core->bus->drv_gmac_cmn.core;
596*dd4544f0SRafał Miłecki 		phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
597*dd4544f0SRafał Miłecki 		phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
598*dd4544f0SRafał Miłecki 	} else {
599*dd4544f0SRafał Miłecki 		core = bgmac->core;
600*dd4544f0SRafał Miłecki 		phy_access_addr = BGMAC_PHY_ACCESS;
601*dd4544f0SRafał Miłecki 		phy_ctl_addr = BGMAC_PHY_CNTL;
602*dd4544f0SRafał Miłecki 	}
603*dd4544f0SRafał Miłecki 
604*dd4544f0SRafał Miłecki 	tmp = bcma_read32(core, phy_ctl_addr);
605*dd4544f0SRafał Miłecki 	tmp &= ~BGMAC_PC_EPA_MASK;
606*dd4544f0SRafał Miłecki 	tmp |= phyaddr;
607*dd4544f0SRafał Miłecki 	bcma_write32(core, phy_ctl_addr, tmp);
608*dd4544f0SRafał Miłecki 
609*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
610*dd4544f0SRafał Miłecki 	if (bgmac_read(bgmac, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
611*dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Error setting MDIO int\n");
612*dd4544f0SRafał Miłecki 
613*dd4544f0SRafał Miłecki 	tmp = BGMAC_PA_START;
614*dd4544f0SRafał Miłecki 	tmp |= BGMAC_PA_WRITE;
615*dd4544f0SRafał Miłecki 	tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
616*dd4544f0SRafał Miłecki 	tmp |= reg << BGMAC_PA_REG_SHIFT;
617*dd4544f0SRafał Miłecki 	tmp |= value;
618*dd4544f0SRafał Miłecki 	bcma_write32(core, phy_access_addr, tmp);
619*dd4544f0SRafał Miłecki 
620*dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000))
621*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Writing to PHY %d register 0x%X failed\n",
622*dd4544f0SRafał Miłecki 			  phyaddr, reg);
623*dd4544f0SRafał Miłecki }
624*dd4544f0SRafał Miłecki 
625*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyforce */
626*dd4544f0SRafał Miłecki static void bgmac_phy_force(struct bgmac *bgmac)
627*dd4544f0SRafał Miłecki {
628*dd4544f0SRafał Miłecki 	u16 ctl;
629*dd4544f0SRafał Miłecki 	u16 mask = ~(BGMAC_PHY_CTL_SPEED | BGMAC_PHY_CTL_SPEED_MSB |
630*dd4544f0SRafał Miłecki 		     BGMAC_PHY_CTL_ANENAB | BGMAC_PHY_CTL_DUPLEX);
631*dd4544f0SRafał Miłecki 
632*dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
633*dd4544f0SRafał Miłecki 		return;
634*dd4544f0SRafał Miłecki 
635*dd4544f0SRafał Miłecki 	if (bgmac->autoneg)
636*dd4544f0SRafał Miłecki 		return;
637*dd4544f0SRafał Miłecki 
638*dd4544f0SRafał Miłecki 	ctl = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL);
639*dd4544f0SRafał Miłecki 	ctl &= mask;
640*dd4544f0SRafał Miłecki 	if (bgmac->full_duplex)
641*dd4544f0SRafał Miłecki 		ctl |= BGMAC_PHY_CTL_DUPLEX;
642*dd4544f0SRafał Miłecki 	if (bgmac->speed == BGMAC_SPEED_100)
643*dd4544f0SRafał Miłecki 		ctl |= BGMAC_PHY_CTL_SPEED_100;
644*dd4544f0SRafał Miłecki 	else if (bgmac->speed == BGMAC_SPEED_1000)
645*dd4544f0SRafał Miłecki 		ctl |= BGMAC_PHY_CTL_SPEED_1000;
646*dd4544f0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, ctl);
647*dd4544f0SRafał Miłecki }
648*dd4544f0SRafał Miłecki 
649*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyadvertise */
650*dd4544f0SRafał Miłecki static void bgmac_phy_advertise(struct bgmac *bgmac)
651*dd4544f0SRafał Miłecki {
652*dd4544f0SRafał Miłecki 	u16 adv;
653*dd4544f0SRafał Miłecki 
654*dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
655*dd4544f0SRafał Miłecki 		return;
656*dd4544f0SRafał Miłecki 
657*dd4544f0SRafał Miłecki 	if (!bgmac->autoneg)
658*dd4544f0SRafał Miłecki 		return;
659*dd4544f0SRafał Miłecki 
660*dd4544f0SRafał Miłecki 	/* Adv selected 10/100 speeds */
661*dd4544f0SRafał Miłecki 	adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV);
662*dd4544f0SRafał Miłecki 	adv &= ~(BGMAC_PHY_ADV_10HALF | BGMAC_PHY_ADV_10FULL |
663*dd4544f0SRafał Miłecki 		 BGMAC_PHY_ADV_100HALF | BGMAC_PHY_ADV_100FULL);
664*dd4544f0SRafał Miłecki 	if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10)
665*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV_10HALF;
666*dd4544f0SRafał Miłecki 	if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100)
667*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV_100HALF;
668*dd4544f0SRafał Miłecki 	if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10)
669*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV_10FULL;
670*dd4544f0SRafał Miłecki 	if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100)
671*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV_100FULL;
672*dd4544f0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV, adv);
673*dd4544f0SRafał Miłecki 
674*dd4544f0SRafał Miłecki 	/* Adv selected 1000 speeds */
675*dd4544f0SRafał Miłecki 	adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2);
676*dd4544f0SRafał Miłecki 	adv &= ~(BGMAC_PHY_ADV2_1000HALF | BGMAC_PHY_ADV2_1000FULL);
677*dd4544f0SRafał Miłecki 	if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000)
678*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV2_1000HALF;
679*dd4544f0SRafał Miłecki 	if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000)
680*dd4544f0SRafał Miłecki 		adv |= BGMAC_PHY_ADV2_1000FULL;
681*dd4544f0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2, adv);
682*dd4544f0SRafał Miłecki 
683*dd4544f0SRafał Miłecki 	/* Restart */
684*dd4544f0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL,
685*dd4544f0SRafał Miłecki 			bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) |
686*dd4544f0SRafał Miłecki 			BGMAC_PHY_CTL_RESTART);
687*dd4544f0SRafał Miłecki }
688*dd4544f0SRafał Miłecki 
689*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
690*dd4544f0SRafał Miłecki static void bgmac_phy_init(struct bgmac *bgmac)
691*dd4544f0SRafał Miłecki {
692*dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
693*dd4544f0SRafał Miłecki 	struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
694*dd4544f0SRafał Miłecki 	u8 i;
695*dd4544f0SRafał Miłecki 
696*dd4544f0SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM5356) {
697*dd4544f0SRafał Miłecki 		for (i = 0; i < 5; i++) {
698*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x008b);
699*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x15, 0x0100);
700*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
701*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x12, 0x2aaa);
702*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
703*dd4544f0SRafał Miłecki 		}
704*dd4544f0SRafał Miłecki 	}
705*dd4544f0SRafał Miłecki 	if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
706*dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
707*dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
708*dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
709*dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
710*dd4544f0SRafał Miłecki 		for (i = 0; i < 5; i++) {
711*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
712*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x5284);
713*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
714*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x0010);
715*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
716*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x5296);
717*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x1073);
718*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x9073);
719*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x52b6);
720*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x9273);
721*dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
722*dd4544f0SRafał Miłecki 		}
723*dd4544f0SRafał Miłecki 	}
724*dd4544f0SRafał Miłecki }
725*dd4544f0SRafał Miłecki 
726*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
727*dd4544f0SRafał Miłecki static void bgmac_phy_reset(struct bgmac *bgmac)
728*dd4544f0SRafał Miłecki {
729*dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
730*dd4544f0SRafał Miłecki 		return;
731*dd4544f0SRafał Miłecki 
732*dd4544f0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL,
733*dd4544f0SRafał Miłecki 			BGMAC_PHY_CTL_RESET);
734*dd4544f0SRafał Miłecki 	udelay(100);
735*dd4544f0SRafał Miłecki 	if (bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) &
736*dd4544f0SRafał Miłecki 	    BGMAC_PHY_CTL_RESET)
737*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "PHY reset failed\n");
738*dd4544f0SRafał Miłecki 	bgmac_phy_init(bgmac);
739*dd4544f0SRafał Miłecki }
740*dd4544f0SRafał Miłecki 
741*dd4544f0SRafał Miłecki /**************************************************
742*dd4544f0SRafał Miłecki  * Chip ops
743*dd4544f0SRafał Miłecki  **************************************************/
744*dd4544f0SRafał Miłecki 
745*dd4544f0SRafał Miłecki /* TODO: can we just drop @force? Can we don't reset MAC at all if there is
746*dd4544f0SRafał Miłecki  * nothing to change? Try if after stabilizng driver.
747*dd4544f0SRafał Miłecki  */
748*dd4544f0SRafał Miłecki static void bgmac_cmdcfg_maskset(struct bgmac *bgmac, u32 mask, u32 set,
749*dd4544f0SRafał Miłecki 				 bool force)
750*dd4544f0SRafał Miłecki {
751*dd4544f0SRafał Miłecki 	u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
752*dd4544f0SRafał Miłecki 	u32 new_val = (cmdcfg & mask) | set;
753*dd4544f0SRafał Miłecki 
754*dd4544f0SRafał Miłecki 	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR);
755*dd4544f0SRafał Miłecki 	udelay(2);
756*dd4544f0SRafał Miłecki 
757*dd4544f0SRafał Miłecki 	if (new_val != cmdcfg || force)
758*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_CMDCFG, new_val);
759*dd4544f0SRafał Miłecki 
760*dd4544f0SRafał Miłecki 	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR);
761*dd4544f0SRafał Miłecki 	udelay(2);
762*dd4544f0SRafał Miłecki }
763*dd4544f0SRafał Miłecki 
764*dd4544f0SRafał Miłecki #if 0 /* We don't use that regs yet */
765*dd4544f0SRafał Miłecki static void bgmac_chip_stats_update(struct bgmac *bgmac)
766*dd4544f0SRafał Miłecki {
767*dd4544f0SRafał Miłecki 	int i;
768*dd4544f0SRafał Miłecki 
769*dd4544f0SRafał Miłecki 	if (bgmac->core->id.id != BCMA_CORE_4706_MAC_GBIT) {
770*dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
771*dd4544f0SRafał Miłecki 			bgmac->mib_tx_regs[i] =
772*dd4544f0SRafał Miłecki 				bgmac_read(bgmac,
773*dd4544f0SRafał Miłecki 					   BGMAC_TX_GOOD_OCTETS + (i * 4));
774*dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
775*dd4544f0SRafał Miłecki 			bgmac->mib_rx_regs[i] =
776*dd4544f0SRafał Miłecki 				bgmac_read(bgmac,
777*dd4544f0SRafał Miłecki 					   BGMAC_RX_GOOD_OCTETS + (i * 4));
778*dd4544f0SRafał Miłecki 	}
779*dd4544f0SRafał Miłecki 
780*dd4544f0SRafał Miłecki 	/* TODO: what else? how to handle BCM4706? Specs are needed */
781*dd4544f0SRafał Miłecki }
782*dd4544f0SRafał Miłecki #endif
783*dd4544f0SRafał Miłecki 
784*dd4544f0SRafał Miłecki static void bgmac_clear_mib(struct bgmac *bgmac)
785*dd4544f0SRafał Miłecki {
786*dd4544f0SRafał Miłecki 	int i;
787*dd4544f0SRafał Miłecki 
788*dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT)
789*dd4544f0SRafał Miłecki 		return;
790*dd4544f0SRafał Miłecki 
791*dd4544f0SRafał Miłecki 	bgmac_set(bgmac, BGMAC_DEV_CTL, BGMAC_DC_MROR);
792*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
793*dd4544f0SRafał Miłecki 		bgmac_read(bgmac, BGMAC_TX_GOOD_OCTETS + (i * 4));
794*dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
795*dd4544f0SRafał Miłecki 		bgmac_read(bgmac, BGMAC_RX_GOOD_OCTETS + (i * 4));
796*dd4544f0SRafał Miłecki }
797*dd4544f0SRafał Miłecki 
798*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_speed */
799*dd4544f0SRafał Miłecki static void bgmac_speed(struct bgmac *bgmac, int speed)
800*dd4544f0SRafał Miłecki {
801*dd4544f0SRafał Miłecki 	u32 mask = ~(BGMAC_CMDCFG_ES_MASK | BGMAC_CMDCFG_HD);
802*dd4544f0SRafał Miłecki 	u32 set = 0;
803*dd4544f0SRafał Miłecki 
804*dd4544f0SRafał Miłecki 	if (speed & BGMAC_SPEED_10)
805*dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_10;
806*dd4544f0SRafał Miłecki 	if (speed & BGMAC_SPEED_100)
807*dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_100;
808*dd4544f0SRafał Miłecki 	if (speed & BGMAC_SPEED_1000)
809*dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_1000;
810*dd4544f0SRafał Miłecki 	if (!bgmac->full_duplex)
811*dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_HD;
812*dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, mask, set, true);
813*dd4544f0SRafał Miłecki }
814*dd4544f0SRafał Miłecki 
815*dd4544f0SRafał Miłecki static void bgmac_miiconfig(struct bgmac *bgmac)
816*dd4544f0SRafał Miłecki {
817*dd4544f0SRafał Miłecki 	u8 imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
818*dd4544f0SRafał Miłecki 			BGMAC_DS_MM_SHIFT;
819*dd4544f0SRafał Miłecki 	if (imode == 0 || imode == 1) {
820*dd4544f0SRafał Miłecki 		if (bgmac->autoneg)
821*dd4544f0SRafał Miłecki 			bgmac_speed(bgmac, BGMAC_SPEED_100);
822*dd4544f0SRafał Miłecki 		else
823*dd4544f0SRafał Miłecki 			bgmac_speed(bgmac, bgmac->speed);
824*dd4544f0SRafał Miłecki 	}
825*dd4544f0SRafał Miłecki }
826*dd4544f0SRafał Miłecki 
827*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipreset */
828*dd4544f0SRafał Miłecki static void bgmac_chip_reset(struct bgmac *bgmac)
829*dd4544f0SRafał Miłecki {
830*dd4544f0SRafał Miłecki 	struct bcma_device *core = bgmac->core;
831*dd4544f0SRafał Miłecki 	struct bcma_bus *bus = core->bus;
832*dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bus->chipinfo;
833*dd4544f0SRafał Miłecki 	u32 flags = 0;
834*dd4544f0SRafał Miłecki 	u32 iost;
835*dd4544f0SRafał Miłecki 	int i;
836*dd4544f0SRafał Miłecki 
837*dd4544f0SRafał Miłecki 	if (bcma_core_is_enabled(core)) {
838*dd4544f0SRafał Miłecki 		if (!bgmac->stats_grabbed) {
839*dd4544f0SRafał Miłecki 			/* bgmac_chip_stats_update(bgmac); */
840*dd4544f0SRafał Miłecki 			bgmac->stats_grabbed = true;
841*dd4544f0SRafał Miłecki 		}
842*dd4544f0SRafał Miłecki 
843*dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
844*dd4544f0SRafał Miłecki 			bgmac_dma_tx_reset(bgmac, &bgmac->tx_ring[i]);
845*dd4544f0SRafał Miłecki 
846*dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
847*dd4544f0SRafał Miłecki 		udelay(1);
848*dd4544f0SRafał Miłecki 
849*dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
850*dd4544f0SRafał Miłecki 			bgmac_dma_rx_reset(bgmac, &bgmac->rx_ring[i]);
851*dd4544f0SRafał Miłecki 
852*dd4544f0SRafał Miłecki 		/* TODO: Clear software multicast filter list */
853*dd4544f0SRafał Miłecki 	}
854*dd4544f0SRafał Miłecki 
855*dd4544f0SRafał Miłecki 	iost = bcma_aread32(core, BCMA_IOST);
856*dd4544f0SRafał Miłecki 	if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 10) ||
857*dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) ||
858*dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9))
859*dd4544f0SRafał Miłecki 		iost &= ~BGMAC_BCMA_IOST_ATTACHED;
860*dd4544f0SRafał Miłecki 
861*dd4544f0SRafał Miłecki 	if (iost & BGMAC_BCMA_IOST_ATTACHED) {
862*dd4544f0SRafał Miłecki 		flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
863*dd4544f0SRafał Miłecki 		if (!bgmac->has_robosw)
864*dd4544f0SRafał Miłecki 			flags |= BGMAC_BCMA_IOCTL_SW_RESET;
865*dd4544f0SRafał Miłecki 	}
866*dd4544f0SRafał Miłecki 
867*dd4544f0SRafał Miłecki 	bcma_core_enable(core, flags);
868*dd4544f0SRafał Miłecki 
869*dd4544f0SRafał Miłecki 	if (core->id.rev > 2) {
870*dd4544f0SRafał Miłecki 		bgmac_set(bgmac, BCMA_CLKCTLST, 1 << 8);
871*dd4544f0SRafał Miłecki 		bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, 1 << 24, 1 << 24,
872*dd4544f0SRafał Miłecki 				 1000);
873*dd4544f0SRafał Miłecki 	}
874*dd4544f0SRafał Miłecki 
875*dd4544f0SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM5357 || ci->id == BCMA_CHIP_ID_BCM4749 ||
876*dd4544f0SRafał Miłecki 	    ci->id == BCMA_CHIP_ID_BCM53572) {
877*dd4544f0SRafał Miłecki 		struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
878*dd4544f0SRafał Miłecki 		u8 et_swtype = 0;
879*dd4544f0SRafał Miłecki 		u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY |
880*dd4544f0SRafał Miłecki 			     BGMAC_CHIPCTL_1_IF_TYPE_RMII;
881*dd4544f0SRafał Miłecki 		char buf[2];
882*dd4544f0SRafał Miłecki 
883*dd4544f0SRafał Miłecki 		if (nvram_getenv("et_swtype", buf, 1) > 0) {
884*dd4544f0SRafał Miłecki 			if (kstrtou8(buf, 0, &et_swtype))
885*dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
886*dd4544f0SRafał Miłecki 					  buf);
887*dd4544f0SRafał Miłecki 			et_swtype &= 0x0f;
888*dd4544f0SRafał Miłecki 			et_swtype <<= 4;
889*dd4544f0SRafał Miłecki 			sw_type = et_swtype;
890*dd4544f0SRafał Miłecki 		} else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 9) {
891*dd4544f0SRafał Miłecki 			sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
892*dd4544f0SRafał Miłecki 		} else if (0) {
893*dd4544f0SRafał Miłecki 			/* TODO */
894*dd4544f0SRafał Miłecki 		}
895*dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 1,
896*dd4544f0SRafał Miłecki 					    ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
897*dd4544f0SRafał Miłecki 					      BGMAC_CHIPCTL_1_SW_TYPE_MASK),
898*dd4544f0SRafał Miłecki 					    sw_type);
899*dd4544f0SRafał Miłecki 	}
900*dd4544f0SRafał Miłecki 
901*dd4544f0SRafał Miłecki 	if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
902*dd4544f0SRafał Miłecki 		bcma_awrite32(core, BCMA_IOCTL,
903*dd4544f0SRafał Miłecki 			      bcma_aread32(core, BCMA_IOCTL) &
904*dd4544f0SRafał Miłecki 			      ~BGMAC_BCMA_IOCTL_SW_RESET);
905*dd4544f0SRafał Miłecki 
906*dd4544f0SRafał Miłecki 	/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_reset
907*dd4544f0SRafał Miłecki 	 * Specs don't say about using BGMAC_CMDCFG_SR, but in this routine
908*dd4544f0SRafał Miłecki 	 * BGMAC_CMDCFG is read _after_ putting chip in a reset. So it has to
909*dd4544f0SRafał Miłecki 	 * be keps until taking MAC out of the reset.
910*dd4544f0SRafał Miłecki 	 */
911*dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac,
912*dd4544f0SRafał Miłecki 			     ~(BGMAC_CMDCFG_TE |
913*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RE |
914*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RPI |
915*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_TAI |
916*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_HD |
917*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_ML |
918*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_CFE |
919*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RL |
920*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RED |
921*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PE |
922*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_TPI |
923*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PAD_EN |
924*dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PF),
925*dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_PROM |
926*dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_NLC |
927*dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_CFE |
928*dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_SR,
929*dd4544f0SRafał Miłecki 			     false);
930*dd4544f0SRafał Miłecki 
931*dd4544f0SRafał Miłecki 	bgmac_clear_mib(bgmac);
932*dd4544f0SRafał Miłecki 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT)
933*dd4544f0SRafał Miłecki 		bcma_maskset32(bgmac->cmn, BCMA_GMAC_CMN_PHY_CTL, ~0,
934*dd4544f0SRafał Miłecki 			       BCMA_GMAC_CMN_PC_MTE);
935*dd4544f0SRafał Miłecki 	else
936*dd4544f0SRafał Miłecki 		bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE);
937*dd4544f0SRafał Miłecki 	bgmac_miiconfig(bgmac);
938*dd4544f0SRafał Miłecki 	bgmac_phy_init(bgmac);
939*dd4544f0SRafał Miłecki 
940*dd4544f0SRafał Miłecki 	bgmac->int_status = 0;
941*dd4544f0SRafał Miłecki }
942*dd4544f0SRafał Miłecki 
943*dd4544f0SRafał Miłecki static void bgmac_chip_intrs_on(struct bgmac *bgmac)
944*dd4544f0SRafał Miłecki {
945*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_MASK, bgmac->int_mask);
946*dd4544f0SRafał Miłecki }
947*dd4544f0SRafał Miłecki 
948*dd4544f0SRafał Miłecki static void bgmac_chip_intrs_off(struct bgmac *bgmac)
949*dd4544f0SRafał Miłecki {
950*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_MASK, 0);
951*dd4544f0SRafał Miłecki }
952*dd4544f0SRafał Miłecki 
953*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_enable */
954*dd4544f0SRafał Miłecki static void bgmac_enable(struct bgmac *bgmac)
955*dd4544f0SRafał Miłecki {
956*dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
957*dd4544f0SRafał Miłecki 	u32 cmdcfg;
958*dd4544f0SRafał Miłecki 	u32 mode;
959*dd4544f0SRafał Miłecki 	u32 rxq_ctl;
960*dd4544f0SRafał Miłecki 	u32 fl_ctl;
961*dd4544f0SRafał Miłecki 	u16 bp_clk;
962*dd4544f0SRafał Miłecki 	u8 mdp;
963*dd4544f0SRafał Miłecki 
964*dd4544f0SRafał Miłecki 	cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
965*dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
966*dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_SR, true);
967*dd4544f0SRafał Miłecki 	udelay(2);
968*dd4544f0SRafał Miłecki 	cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
969*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);
970*dd4544f0SRafał Miłecki 
971*dd4544f0SRafał Miłecki 	mode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
972*dd4544f0SRafał Miłecki 		BGMAC_DS_MM_SHIFT;
973*dd4544f0SRafał Miłecki 	if (ci->id != BCMA_CHIP_ID_BCM47162 || mode != 0)
974*dd4544f0SRafał Miłecki 		bgmac_set(bgmac, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
975*dd4544f0SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM47162 && mode == 2)
976*dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(&bgmac->core->bus->drv_cc, 1, ~0,
977*dd4544f0SRafał Miłecki 					    BGMAC_CHIPCTL_1_RXC_DLL_BYPASS);
978*dd4544f0SRafał Miłecki 
979*dd4544f0SRafał Miłecki 	switch (ci->id) {
980*dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM5357:
981*dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM4749:
982*dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM53572:
983*dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM4716:
984*dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM47162:
985*dd4544f0SRafał Miłecki 		fl_ctl = 0x03cb04cb;
986*dd4544f0SRafał Miłecki 		if (ci->id == BCMA_CHIP_ID_BCM5357 ||
987*dd4544f0SRafał Miłecki 		    ci->id == BCMA_CHIP_ID_BCM4749 ||
988*dd4544f0SRafał Miłecki 		    ci->id == BCMA_CHIP_ID_BCM53572)
989*dd4544f0SRafał Miłecki 			fl_ctl = 0x2300e1;
990*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_FLOW_CTL_THRESH, fl_ctl);
991*dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_PAUSE_CTL, 0x27fff);
992*dd4544f0SRafał Miłecki 		break;
993*dd4544f0SRafał Miłecki 	}
994*dd4544f0SRafał Miłecki 
995*dd4544f0SRafał Miłecki 	rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
996*dd4544f0SRafał Miłecki 	rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
997*dd4544f0SRafał Miłecki 	bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) / 1000000;
998*dd4544f0SRafał Miłecki 	mdp = (bp_clk * 128 / 1000) - 3;
999*dd4544f0SRafał Miłecki 	rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
1000*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
1001*dd4544f0SRafał Miłecki }
1002*dd4544f0SRafał Miłecki 
1003*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
1004*dd4544f0SRafał Miłecki static void bgmac_chip_init(struct bgmac *bgmac, bool full_init)
1005*dd4544f0SRafał Miłecki {
1006*dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1007*dd4544f0SRafał Miłecki 	u8 *mac = bgmac->net_dev->dev_addr;
1008*dd4544f0SRafał Miłecki 	u32 tmp;
1009*dd4544f0SRafał Miłecki 	int i;
1010*dd4544f0SRafał Miłecki 
1011*dd4544f0SRafał Miłecki 	/* 1 interrupt per received frame */
1012*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);
1013*dd4544f0SRafał Miłecki 
1014*dd4544f0SRafał Miłecki 	/* Enable 802.3x tx flow control (honor received PAUSE frames) */
1015*dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_RPI, 0, true);
1016*dd4544f0SRafał Miłecki 
1017*dd4544f0SRafał Miłecki 	if (bgmac->net_dev->flags & IFF_PROMISC)
1018*dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, false);
1019*dd4544f0SRafał Miłecki 	else
1020*dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, false);
1021*dd4544f0SRafał Miłecki 
1022*dd4544f0SRafał Miłecki 	/* Set MAC addr */
1023*dd4544f0SRafał Miłecki 	tmp = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
1024*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
1025*dd4544f0SRafał Miłecki 	tmp = (mac[4] << 8) | mac[5];
1026*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
1027*dd4544f0SRafał Miłecki 
1028*dd4544f0SRafał Miłecki 	if (bgmac->loopback)
1029*dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, true);
1030*dd4544f0SRafał Miłecki 	else
1031*dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_ML, 0, true);
1032*dd4544f0SRafał Miłecki 
1033*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN);
1034*dd4544f0SRafał Miłecki 
1035*dd4544f0SRafał Miłecki 	if (!bgmac->autoneg) {
1036*dd4544f0SRafał Miłecki 		bgmac_speed(bgmac, bgmac->speed);
1037*dd4544f0SRafał Miłecki 		bgmac_phy_force(bgmac);
1038*dd4544f0SRafał Miłecki 	} else if (bgmac->speed) { /* if there is anything to adv */
1039*dd4544f0SRafał Miłecki 		bgmac_phy_advertise(bgmac);
1040*dd4544f0SRafał Miłecki 	}
1041*dd4544f0SRafał Miłecki 
1042*dd4544f0SRafał Miłecki 	if (full_init) {
1043*dd4544f0SRafał Miłecki 		bgmac_dma_init(bgmac);
1044*dd4544f0SRafał Miłecki 		if (1) /* FIXME: is there any case we don't want IRQs? */
1045*dd4544f0SRafał Miłecki 			bgmac_chip_intrs_on(bgmac);
1046*dd4544f0SRafał Miłecki 	} else {
1047*dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
1048*dd4544f0SRafał Miłecki 			ring = &bgmac->rx_ring[i];
1049*dd4544f0SRafał Miłecki 			bgmac_dma_rx_enable(bgmac, ring);
1050*dd4544f0SRafał Miłecki 		}
1051*dd4544f0SRafał Miłecki 	}
1052*dd4544f0SRafał Miłecki 
1053*dd4544f0SRafał Miłecki 	bgmac_enable(bgmac);
1054*dd4544f0SRafał Miłecki }
1055*dd4544f0SRafał Miłecki 
1056*dd4544f0SRafał Miłecki static irqreturn_t bgmac_interrupt(int irq, void *dev_id)
1057*dd4544f0SRafał Miłecki {
1058*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(dev_id);
1059*dd4544f0SRafał Miłecki 
1060*dd4544f0SRafał Miłecki 	u32 int_status = bgmac_read(bgmac, BGMAC_INT_STATUS);
1061*dd4544f0SRafał Miłecki 	int_status &= bgmac->int_mask;
1062*dd4544f0SRafał Miłecki 
1063*dd4544f0SRafał Miłecki 	if (!int_status)
1064*dd4544f0SRafał Miłecki 		return IRQ_NONE;
1065*dd4544f0SRafał Miłecki 
1066*dd4544f0SRafał Miłecki 	/* Ack */
1067*dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_STATUS, int_status);
1068*dd4544f0SRafał Miłecki 
1069*dd4544f0SRafał Miłecki 	/* Disable new interrupts until handling existing ones */
1070*dd4544f0SRafał Miłecki 	bgmac_chip_intrs_off(bgmac);
1071*dd4544f0SRafał Miłecki 
1072*dd4544f0SRafał Miłecki 	bgmac->int_status = int_status;
1073*dd4544f0SRafał Miłecki 
1074*dd4544f0SRafał Miłecki 	napi_schedule(&bgmac->napi);
1075*dd4544f0SRafał Miłecki 
1076*dd4544f0SRafał Miłecki 	return IRQ_HANDLED;
1077*dd4544f0SRafał Miłecki }
1078*dd4544f0SRafał Miłecki 
1079*dd4544f0SRafał Miłecki static int bgmac_poll(struct napi_struct *napi, int weight)
1080*dd4544f0SRafał Miłecki {
1081*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = container_of(napi, struct bgmac, napi);
1082*dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1083*dd4544f0SRafał Miłecki 	int handled = 0;
1084*dd4544f0SRafał Miłecki 
1085*dd4544f0SRafał Miłecki 	if (bgmac->int_status & BGMAC_IS_TX0) {
1086*dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[0];
1087*dd4544f0SRafał Miłecki 		bgmac_dma_tx_free(bgmac, ring);
1088*dd4544f0SRafał Miłecki 		bgmac->int_status &= ~BGMAC_IS_TX0;
1089*dd4544f0SRafał Miłecki 	}
1090*dd4544f0SRafał Miłecki 
1091*dd4544f0SRafał Miłecki 	if (bgmac->int_status & BGMAC_IS_RX) {
1092*dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[0];
1093*dd4544f0SRafał Miłecki 		handled += bgmac_dma_rx_read(bgmac, ring, weight);
1094*dd4544f0SRafał Miłecki 		bgmac->int_status &= ~BGMAC_IS_RX;
1095*dd4544f0SRafał Miłecki 	}
1096*dd4544f0SRafał Miłecki 
1097*dd4544f0SRafał Miłecki 	if (bgmac->int_status) {
1098*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", bgmac->int_status);
1099*dd4544f0SRafał Miłecki 		bgmac->int_status = 0;
1100*dd4544f0SRafał Miłecki 	}
1101*dd4544f0SRafał Miłecki 
1102*dd4544f0SRafał Miłecki 	if (handled < weight)
1103*dd4544f0SRafał Miłecki 		napi_complete(napi);
1104*dd4544f0SRafał Miłecki 
1105*dd4544f0SRafał Miłecki 	bgmac_chip_intrs_on(bgmac);
1106*dd4544f0SRafał Miłecki 
1107*dd4544f0SRafał Miłecki 	return handled;
1108*dd4544f0SRafał Miłecki }
1109*dd4544f0SRafał Miłecki 
1110*dd4544f0SRafał Miłecki /**************************************************
1111*dd4544f0SRafał Miłecki  * net_device_ops
1112*dd4544f0SRafał Miłecki  **************************************************/
1113*dd4544f0SRafał Miłecki 
1114*dd4544f0SRafał Miłecki static int bgmac_open(struct net_device *net_dev)
1115*dd4544f0SRafał Miłecki {
1116*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1117*dd4544f0SRafał Miłecki 	int err = 0;
1118*dd4544f0SRafał Miłecki 
1119*dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1120*dd4544f0SRafał Miłecki 	/* Specs say about reclaiming rings here, but we do that in DMA init */
1121*dd4544f0SRafał Miłecki 	bgmac_chip_init(bgmac, true);
1122*dd4544f0SRafał Miłecki 
1123*dd4544f0SRafał Miłecki 	err = request_irq(bgmac->core->irq, bgmac_interrupt, IRQF_SHARED,
1124*dd4544f0SRafał Miłecki 			  KBUILD_MODNAME, net_dev);
1125*dd4544f0SRafał Miłecki 	if (err < 0) {
1126*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "IRQ request error: %d!\n", err);
1127*dd4544f0SRafał Miłecki 		goto err_out;
1128*dd4544f0SRafał Miłecki 	}
1129*dd4544f0SRafał Miłecki 	napi_enable(&bgmac->napi);
1130*dd4544f0SRafał Miłecki 
1131*dd4544f0SRafał Miłecki 	netif_carrier_on(net_dev);
1132*dd4544f0SRafał Miłecki 
1133*dd4544f0SRafał Miłecki err_out:
1134*dd4544f0SRafał Miłecki 	return err;
1135*dd4544f0SRafał Miłecki }
1136*dd4544f0SRafał Miłecki 
1137*dd4544f0SRafał Miłecki static int bgmac_stop(struct net_device *net_dev)
1138*dd4544f0SRafał Miłecki {
1139*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1140*dd4544f0SRafał Miłecki 
1141*dd4544f0SRafał Miłecki 	netif_carrier_off(net_dev);
1142*dd4544f0SRafał Miłecki 
1143*dd4544f0SRafał Miłecki 	napi_disable(&bgmac->napi);
1144*dd4544f0SRafał Miłecki 	bgmac_chip_intrs_off(bgmac);
1145*dd4544f0SRafał Miłecki 	free_irq(bgmac->core->irq, net_dev);
1146*dd4544f0SRafał Miłecki 
1147*dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1148*dd4544f0SRafał Miłecki 
1149*dd4544f0SRafał Miłecki 	return 0;
1150*dd4544f0SRafał Miłecki }
1151*dd4544f0SRafał Miłecki 
1152*dd4544f0SRafał Miłecki static netdev_tx_t bgmac_start_xmit(struct sk_buff *skb,
1153*dd4544f0SRafał Miłecki 				    struct net_device *net_dev)
1154*dd4544f0SRafał Miłecki {
1155*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1156*dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1157*dd4544f0SRafał Miłecki 
1158*dd4544f0SRafał Miłecki 	/* No QOS support yet */
1159*dd4544f0SRafał Miłecki 	ring = &bgmac->tx_ring[0];
1160*dd4544f0SRafał Miłecki 	return bgmac_dma_tx_add(bgmac, ring, skb);
1161*dd4544f0SRafał Miłecki }
1162*dd4544f0SRafał Miłecki 
1163*dd4544f0SRafał Miłecki static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
1164*dd4544f0SRafał Miłecki {
1165*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1166*dd4544f0SRafał Miłecki 	struct mii_ioctl_data *data = if_mii(ifr);
1167*dd4544f0SRafał Miłecki 
1168*dd4544f0SRafał Miłecki 	switch (cmd) {
1169*dd4544f0SRafał Miłecki 	case SIOCGMIIPHY:
1170*dd4544f0SRafał Miłecki 		data->phy_id = bgmac->phyaddr;
1171*dd4544f0SRafał Miłecki 		/* fallthru */
1172*dd4544f0SRafał Miłecki 	case SIOCGMIIREG:
1173*dd4544f0SRafał Miłecki 		if (!netif_running(net_dev))
1174*dd4544f0SRafał Miłecki 			return -EAGAIN;
1175*dd4544f0SRafał Miłecki 		data->val_out = bgmac_phy_read(bgmac, data->phy_id,
1176*dd4544f0SRafał Miłecki 					       data->reg_num & 0x1f);
1177*dd4544f0SRafał Miłecki 		return 0;
1178*dd4544f0SRafał Miłecki 	case SIOCSMIIREG:
1179*dd4544f0SRafał Miłecki 		if (!netif_running(net_dev))
1180*dd4544f0SRafał Miłecki 			return -EAGAIN;
1181*dd4544f0SRafał Miłecki 		bgmac_phy_write(bgmac, data->phy_id, data->reg_num & 0x1f,
1182*dd4544f0SRafał Miłecki 				data->val_in);
1183*dd4544f0SRafał Miłecki 		return 0;
1184*dd4544f0SRafał Miłecki 	default:
1185*dd4544f0SRafał Miłecki 		return -EOPNOTSUPP;
1186*dd4544f0SRafał Miłecki 	}
1187*dd4544f0SRafał Miłecki }
1188*dd4544f0SRafał Miłecki 
1189*dd4544f0SRafał Miłecki static const struct net_device_ops bgmac_netdev_ops = {
1190*dd4544f0SRafał Miłecki 	.ndo_open		= bgmac_open,
1191*dd4544f0SRafał Miłecki 	.ndo_stop		= bgmac_stop,
1192*dd4544f0SRafał Miłecki 	.ndo_start_xmit		= bgmac_start_xmit,
1193*dd4544f0SRafał Miłecki 	.ndo_set_mac_address	= eth_mac_addr, /* generic, sets dev_addr */
1194*dd4544f0SRafał Miłecki 	.ndo_do_ioctl           = bgmac_ioctl,
1195*dd4544f0SRafał Miłecki };
1196*dd4544f0SRafał Miłecki 
1197*dd4544f0SRafał Miłecki /**************************************************
1198*dd4544f0SRafał Miłecki  * ethtool_ops
1199*dd4544f0SRafał Miłecki  **************************************************/
1200*dd4544f0SRafał Miłecki 
1201*dd4544f0SRafał Miłecki static int bgmac_get_settings(struct net_device *net_dev,
1202*dd4544f0SRafał Miłecki 			      struct ethtool_cmd *cmd)
1203*dd4544f0SRafał Miłecki {
1204*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1205*dd4544f0SRafał Miłecki 
1206*dd4544f0SRafał Miłecki 	cmd->supported = SUPPORTED_10baseT_Half |
1207*dd4544f0SRafał Miłecki 			 SUPPORTED_10baseT_Full |
1208*dd4544f0SRafał Miłecki 			 SUPPORTED_100baseT_Half |
1209*dd4544f0SRafał Miłecki 			 SUPPORTED_100baseT_Full |
1210*dd4544f0SRafał Miłecki 			 SUPPORTED_1000baseT_Half |
1211*dd4544f0SRafał Miłecki 			 SUPPORTED_1000baseT_Full |
1212*dd4544f0SRafał Miłecki 			 SUPPORTED_Autoneg;
1213*dd4544f0SRafał Miłecki 
1214*dd4544f0SRafał Miłecki 	if (bgmac->autoneg) {
1215*dd4544f0SRafał Miłecki 		WARN_ON(cmd->advertising);
1216*dd4544f0SRafał Miłecki 		if (bgmac->full_duplex) {
1217*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_10)
1218*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_10baseT_Full;
1219*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_100)
1220*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_100baseT_Full;
1221*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_1000)
1222*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_1000baseT_Full;
1223*dd4544f0SRafał Miłecki 		} else {
1224*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_10)
1225*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_10baseT_Half;
1226*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_100)
1227*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_100baseT_Half;
1228*dd4544f0SRafał Miłecki 			if (bgmac->speed & BGMAC_SPEED_1000)
1229*dd4544f0SRafał Miłecki 				cmd->advertising |= ADVERTISED_1000baseT_Half;
1230*dd4544f0SRafał Miłecki 		}
1231*dd4544f0SRafał Miłecki 	} else {
1232*dd4544f0SRafał Miłecki 		switch (bgmac->speed) {
1233*dd4544f0SRafał Miłecki 		case BGMAC_SPEED_10:
1234*dd4544f0SRafał Miłecki 			ethtool_cmd_speed_set(cmd, SPEED_10);
1235*dd4544f0SRafał Miłecki 			break;
1236*dd4544f0SRafał Miłecki 		case BGMAC_SPEED_100:
1237*dd4544f0SRafał Miłecki 			ethtool_cmd_speed_set(cmd, SPEED_100);
1238*dd4544f0SRafał Miłecki 			break;
1239*dd4544f0SRafał Miłecki 		case BGMAC_SPEED_1000:
1240*dd4544f0SRafał Miłecki 			ethtool_cmd_speed_set(cmd, SPEED_1000);
1241*dd4544f0SRafał Miłecki 			break;
1242*dd4544f0SRafał Miłecki 		}
1243*dd4544f0SRafał Miłecki 	}
1244*dd4544f0SRafał Miłecki 
1245*dd4544f0SRafał Miłecki 	cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
1246*dd4544f0SRafał Miłecki 
1247*dd4544f0SRafał Miłecki 	cmd->autoneg = bgmac->autoneg;
1248*dd4544f0SRafał Miłecki 
1249*dd4544f0SRafał Miłecki 	return 0;
1250*dd4544f0SRafał Miłecki }
1251*dd4544f0SRafał Miłecki 
1252*dd4544f0SRafał Miłecki #if 0
1253*dd4544f0SRafał Miłecki static int bgmac_set_settings(struct net_device *net_dev,
1254*dd4544f0SRafał Miłecki 			      struct ethtool_cmd *cmd)
1255*dd4544f0SRafał Miłecki {
1256*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1257*dd4544f0SRafał Miłecki 
1258*dd4544f0SRafał Miłecki 	return -1;
1259*dd4544f0SRafał Miłecki }
1260*dd4544f0SRafał Miłecki #endif
1261*dd4544f0SRafał Miłecki 
1262*dd4544f0SRafał Miłecki static void bgmac_get_drvinfo(struct net_device *net_dev,
1263*dd4544f0SRafał Miłecki 			      struct ethtool_drvinfo *info)
1264*dd4544f0SRafał Miłecki {
1265*dd4544f0SRafał Miłecki 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
1266*dd4544f0SRafał Miłecki 	strlcpy(info->bus_info, "BCMA", sizeof(info->bus_info));
1267*dd4544f0SRafał Miłecki }
1268*dd4544f0SRafał Miłecki 
1269*dd4544f0SRafał Miłecki static const struct ethtool_ops bgmac_ethtool_ops = {
1270*dd4544f0SRafał Miłecki 	.get_settings		= bgmac_get_settings,
1271*dd4544f0SRafał Miłecki 	.get_drvinfo		= bgmac_get_drvinfo,
1272*dd4544f0SRafał Miłecki };
1273*dd4544f0SRafał Miłecki 
1274*dd4544f0SRafał Miłecki /**************************************************
1275*dd4544f0SRafał Miłecki  * BCMA bus ops
1276*dd4544f0SRafał Miłecki  **************************************************/
1277*dd4544f0SRafał Miłecki 
1278*dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
1279*dd4544f0SRafał Miłecki static int bgmac_probe(struct bcma_device *core)
1280*dd4544f0SRafał Miłecki {
1281*dd4544f0SRafał Miłecki 	struct net_device *net_dev;
1282*dd4544f0SRafał Miłecki 	struct bgmac *bgmac;
1283*dd4544f0SRafał Miłecki 	struct ssb_sprom *sprom = &core->bus->sprom;
1284*dd4544f0SRafał Miłecki 	u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac;
1285*dd4544f0SRafał Miłecki 	int err;
1286*dd4544f0SRafał Miłecki 
1287*dd4544f0SRafał Miłecki 	/* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */
1288*dd4544f0SRafał Miłecki 	if (core->core_unit > 1) {
1289*dd4544f0SRafał Miłecki 		pr_err("Unsupported core_unit %d\n", core->core_unit);
1290*dd4544f0SRafał Miłecki 		return -ENOTSUPP;
1291*dd4544f0SRafał Miłecki 	}
1292*dd4544f0SRafał Miłecki 
1293*dd4544f0SRafał Miłecki 	/* Allocation and references */
1294*dd4544f0SRafał Miłecki 	net_dev = alloc_etherdev(sizeof(*bgmac));
1295*dd4544f0SRafał Miłecki 	if (!net_dev)
1296*dd4544f0SRafał Miłecki 		return -ENOMEM;
1297*dd4544f0SRafał Miłecki 	net_dev->netdev_ops = &bgmac_netdev_ops;
1298*dd4544f0SRafał Miłecki 	net_dev->irq = core->irq;
1299*dd4544f0SRafał Miłecki 	SET_ETHTOOL_OPS(net_dev, &bgmac_ethtool_ops);
1300*dd4544f0SRafał Miłecki 	bgmac = netdev_priv(net_dev);
1301*dd4544f0SRafał Miłecki 	bgmac->net_dev = net_dev;
1302*dd4544f0SRafał Miłecki 	bgmac->core = core;
1303*dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, bgmac);
1304*dd4544f0SRafał Miłecki 
1305*dd4544f0SRafał Miłecki 	/* Defaults */
1306*dd4544f0SRafał Miłecki 	bgmac->autoneg = true;
1307*dd4544f0SRafał Miłecki 	bgmac->full_duplex = true;
1308*dd4544f0SRafał Miłecki 	bgmac->speed = BGMAC_SPEED_10 | BGMAC_SPEED_100 | BGMAC_SPEED_1000;
1309*dd4544f0SRafał Miłecki 	memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
1310*dd4544f0SRafał Miłecki 
1311*dd4544f0SRafał Miłecki 	/* On BCM4706 we need common core to access PHY */
1312*dd4544f0SRafał Miłecki 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
1313*dd4544f0SRafał Miłecki 	    !core->bus->drv_gmac_cmn.core) {
1314*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "GMAC CMN core not found (required for BCM4706)\n");
1315*dd4544f0SRafał Miłecki 		err = -ENODEV;
1316*dd4544f0SRafał Miłecki 		goto err_netdev_free;
1317*dd4544f0SRafał Miłecki 	}
1318*dd4544f0SRafał Miłecki 	bgmac->cmn = core->bus->drv_gmac_cmn.core;
1319*dd4544f0SRafał Miłecki 
1320*dd4544f0SRafał Miłecki 	bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr :
1321*dd4544f0SRafał Miłecki 			 sprom->et0phyaddr;
1322*dd4544f0SRafał Miłecki 	bgmac->phyaddr &= BGMAC_PHY_MASK;
1323*dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
1324*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "No PHY found\n");
1325*dd4544f0SRafał Miłecki 		err = -ENODEV;
1326*dd4544f0SRafał Miłecki 		goto err_netdev_free;
1327*dd4544f0SRafał Miłecki 	}
1328*dd4544f0SRafał Miłecki 	bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr,
1329*dd4544f0SRafał Miłecki 		   bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
1330*dd4544f0SRafał Miłecki 
1331*dd4544f0SRafał Miłecki 	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
1332*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "PCI setup not implemented\n");
1333*dd4544f0SRafał Miłecki 		err = -ENOTSUPP;
1334*dd4544f0SRafał Miłecki 		goto err_netdev_free;
1335*dd4544f0SRafał Miłecki 	}
1336*dd4544f0SRafał Miłecki 
1337*dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1338*dd4544f0SRafał Miłecki 
1339*dd4544f0SRafał Miłecki 	err = bgmac_dma_alloc(bgmac);
1340*dd4544f0SRafał Miłecki 	if (err) {
1341*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Unable to alloc memory for DMA\n");
1342*dd4544f0SRafał Miłecki 		goto err_netdev_free;
1343*dd4544f0SRafał Miłecki 	}
1344*dd4544f0SRafał Miłecki 
1345*dd4544f0SRafał Miłecki 	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
1346*dd4544f0SRafał Miłecki 	if (nvram_getenv("et0_no_txint", NULL, 0) == 0)
1347*dd4544f0SRafał Miłecki 		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;
1348*dd4544f0SRafał Miłecki 
1349*dd4544f0SRafał Miłecki 	/* TODO: reset the external phy. Specs are needed */
1350*dd4544f0SRafał Miłecki 	bgmac_phy_reset(bgmac);
1351*dd4544f0SRafał Miłecki 
1352*dd4544f0SRafał Miłecki 	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
1353*dd4544f0SRafał Miłecki 			       BGMAC_BFL_ENETROBO);
1354*dd4544f0SRafał Miłecki 	if (bgmac->has_robosw)
1355*dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Support for Roboswitch not implemented\n");
1356*dd4544f0SRafał Miłecki 
1357*dd4544f0SRafał Miłecki 	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
1358*dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
1359*dd4544f0SRafał Miłecki 
1360*dd4544f0SRafał Miłecki 	err = register_netdev(bgmac->net_dev);
1361*dd4544f0SRafał Miłecki 	if (err) {
1362*dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Cannot register net device\n");
1363*dd4544f0SRafał Miłecki 		err = -ENOTSUPP;
1364*dd4544f0SRafał Miłecki 		goto err_dma_free;
1365*dd4544f0SRafał Miłecki 	}
1366*dd4544f0SRafał Miłecki 
1367*dd4544f0SRafał Miłecki 	netif_carrier_off(net_dev);
1368*dd4544f0SRafał Miłecki 
1369*dd4544f0SRafał Miłecki 	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
1370*dd4544f0SRafał Miłecki 
1371*dd4544f0SRafał Miłecki 	return 0;
1372*dd4544f0SRafał Miłecki 
1373*dd4544f0SRafał Miłecki err_dma_free:
1374*dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
1375*dd4544f0SRafał Miłecki 
1376*dd4544f0SRafał Miłecki err_netdev_free:
1377*dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, NULL);
1378*dd4544f0SRafał Miłecki 	free_netdev(net_dev);
1379*dd4544f0SRafał Miłecki 
1380*dd4544f0SRafał Miłecki 	return err;
1381*dd4544f0SRafał Miłecki }
1382*dd4544f0SRafał Miłecki 
1383*dd4544f0SRafał Miłecki static void bgmac_remove(struct bcma_device *core)
1384*dd4544f0SRafał Miłecki {
1385*dd4544f0SRafał Miłecki 	struct bgmac *bgmac = bcma_get_drvdata(core);
1386*dd4544f0SRafał Miłecki 
1387*dd4544f0SRafał Miłecki 	netif_napi_del(&bgmac->napi);
1388*dd4544f0SRafał Miłecki 	unregister_netdev(bgmac->net_dev);
1389*dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
1390*dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, NULL);
1391*dd4544f0SRafał Miłecki 	free_netdev(bgmac->net_dev);
1392*dd4544f0SRafał Miłecki }
1393*dd4544f0SRafał Miłecki 
1394*dd4544f0SRafał Miłecki static struct bcma_driver bgmac_bcma_driver = {
1395*dd4544f0SRafał Miłecki 	.name		= KBUILD_MODNAME,
1396*dd4544f0SRafał Miłecki 	.id_table	= bgmac_bcma_tbl,
1397*dd4544f0SRafał Miłecki 	.probe		= bgmac_probe,
1398*dd4544f0SRafał Miłecki 	.remove		= bgmac_remove,
1399*dd4544f0SRafał Miłecki };
1400*dd4544f0SRafał Miłecki 
1401*dd4544f0SRafał Miłecki static int __init bgmac_init(void)
1402*dd4544f0SRafał Miłecki {
1403*dd4544f0SRafał Miłecki 	int err;
1404*dd4544f0SRafał Miłecki 
1405*dd4544f0SRafał Miłecki 	err = bcma_driver_register(&bgmac_bcma_driver);
1406*dd4544f0SRafał Miłecki 	if (err)
1407*dd4544f0SRafał Miłecki 		return err;
1408*dd4544f0SRafał Miłecki 	pr_info("Broadcom 47xx GBit MAC driver loaded\n");
1409*dd4544f0SRafał Miłecki 
1410*dd4544f0SRafał Miłecki 	return 0;
1411*dd4544f0SRafał Miłecki }
1412*dd4544f0SRafał Miłecki 
1413*dd4544f0SRafał Miłecki static void __exit bgmac_exit(void)
1414*dd4544f0SRafał Miłecki {
1415*dd4544f0SRafał Miłecki 	bcma_driver_unregister(&bgmac_bcma_driver);
1416*dd4544f0SRafał Miłecki }
1417*dd4544f0SRafał Miłecki 
1418*dd4544f0SRafał Miłecki module_init(bgmac_init)
1419*dd4544f0SRafał Miłecki module_exit(bgmac_exit)
1420*dd4544f0SRafał Miłecki 
1421*dd4544f0SRafał Miłecki MODULE_AUTHOR("Rafał Miłecki");
1422*dd4544f0SRafał Miłecki MODULE_LICENSE("GPL");
1423