xref: /openbmc/linux/drivers/net/ethernet/broadcom/bgmac.c (revision 138173d4e826587da66c7d321da1a91283222536)
1dd4544f0SRafał Miłecki /*
2dd4544f0SRafał Miłecki  * Driver for (BCM4706)? GBit MAC core on BCMA bus.
3dd4544f0SRafał Miłecki  *
4dd4544f0SRafał Miłecki  * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
5dd4544f0SRafał Miłecki  *
6dd4544f0SRafał Miłecki  * Licensed under the GNU/GPL. See COPYING for details.
7dd4544f0SRafał Miłecki  */
8dd4544f0SRafał Miłecki 
9dd4544f0SRafał Miłecki #include "bgmac.h"
10dd4544f0SRafał Miłecki 
11dd4544f0SRafał Miłecki #include <linux/kernel.h>
12dd4544f0SRafał Miłecki #include <linux/module.h>
13dd4544f0SRafał Miłecki #include <linux/delay.h>
14dd4544f0SRafał Miłecki #include <linux/etherdevice.h>
15dd4544f0SRafał Miłecki #include <linux/mii.h>
1611e5e76eSRafał Miłecki #include <linux/phy.h>
17dd4544f0SRafał Miłecki #include <linux/interrupt.h>
18dd4544f0SRafał Miłecki #include <linux/dma-mapping.h>
19*138173d4SRafał Miłecki #include <linux/bcm47xx_nvram.h>
20dd4544f0SRafał Miłecki 
21dd4544f0SRafał Miłecki static const struct bcma_device_id bgmac_bcma_tbl[] = {
22dd4544f0SRafał Miłecki 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
23dd4544f0SRafał Miłecki 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
24f7219b52SJoe Perches 	{},
25dd4544f0SRafał Miłecki };
26dd4544f0SRafał Miłecki MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
27dd4544f0SRafał Miłecki 
28dd4544f0SRafał Miłecki static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask,
29dd4544f0SRafał Miłecki 			     u32 value, int timeout)
30dd4544f0SRafał Miłecki {
31dd4544f0SRafał Miłecki 	u32 val;
32dd4544f0SRafał Miłecki 	int i;
33dd4544f0SRafał Miłecki 
34dd4544f0SRafał Miłecki 	for (i = 0; i < timeout / 10; i++) {
35dd4544f0SRafał Miłecki 		val = bcma_read32(core, reg);
36dd4544f0SRafał Miłecki 		if ((val & mask) == value)
37dd4544f0SRafał Miłecki 			return true;
38dd4544f0SRafał Miłecki 		udelay(10);
39dd4544f0SRafał Miłecki 	}
40dd4544f0SRafał Miłecki 	pr_err("Timeout waiting for reg 0x%X\n", reg);
41dd4544f0SRafał Miłecki 	return false;
42dd4544f0SRafał Miłecki }
43dd4544f0SRafał Miłecki 
44dd4544f0SRafał Miłecki /**************************************************
45dd4544f0SRafał Miłecki  * DMA
46dd4544f0SRafał Miłecki  **************************************************/
47dd4544f0SRafał Miłecki 
48dd4544f0SRafał Miłecki static void bgmac_dma_tx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
49dd4544f0SRafał Miłecki {
50dd4544f0SRafał Miłecki 	u32 val;
51dd4544f0SRafał Miłecki 	int i;
52dd4544f0SRafał Miłecki 
53dd4544f0SRafał Miłecki 	if (!ring->mmio_base)
54dd4544f0SRafał Miłecki 		return;
55dd4544f0SRafał Miłecki 
56dd4544f0SRafał Miłecki 	/* Suspend DMA TX ring first.
57dd4544f0SRafał Miłecki 	 * bgmac_wait_value doesn't support waiting for any of few values, so
58dd4544f0SRafał Miłecki 	 * implement whole loop here.
59dd4544f0SRafał Miłecki 	 */
60dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL,
61dd4544f0SRafał Miłecki 		    BGMAC_DMA_TX_SUSPEND);
62dd4544f0SRafał Miłecki 	for (i = 0; i < 10000 / 10; i++) {
63dd4544f0SRafał Miłecki 		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
64dd4544f0SRafał Miłecki 		val &= BGMAC_DMA_TX_STAT;
65dd4544f0SRafał Miłecki 		if (val == BGMAC_DMA_TX_STAT_DISABLED ||
66dd4544f0SRafał Miłecki 		    val == BGMAC_DMA_TX_STAT_IDLEWAIT ||
67dd4544f0SRafał Miłecki 		    val == BGMAC_DMA_TX_STAT_STOPPED) {
68dd4544f0SRafał Miłecki 			i = 0;
69dd4544f0SRafał Miłecki 			break;
70dd4544f0SRafał Miłecki 		}
71dd4544f0SRafał Miłecki 		udelay(10);
72dd4544f0SRafał Miłecki 	}
73dd4544f0SRafał Miłecki 	if (i)
74dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Timeout suspending DMA TX ring 0x%X (BGMAC_DMA_TX_STAT: 0x%08X)\n",
75dd4544f0SRafał Miłecki 			  ring->mmio_base, val);
76dd4544f0SRafał Miłecki 
77dd4544f0SRafał Miłecki 	/* Remove SUSPEND bit */
78dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, 0);
79dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(bgmac->core,
80dd4544f0SRafał Miłecki 			      ring->mmio_base + BGMAC_DMA_TX_STATUS,
81dd4544f0SRafał Miłecki 			      BGMAC_DMA_TX_STAT, BGMAC_DMA_TX_STAT_DISABLED,
82dd4544f0SRafał Miłecki 			      10000)) {
83dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "DMA TX ring 0x%X wasn't disabled on time, waiting additional 300us\n",
84dd4544f0SRafał Miłecki 			   ring->mmio_base);
85dd4544f0SRafał Miłecki 		udelay(300);
86dd4544f0SRafał Miłecki 		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
87dd4544f0SRafał Miłecki 		if ((val & BGMAC_DMA_TX_STAT) != BGMAC_DMA_TX_STAT_DISABLED)
88dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Reset of DMA TX ring 0x%X failed\n",
89dd4544f0SRafał Miłecki 				  ring->mmio_base);
90dd4544f0SRafał Miłecki 	}
91dd4544f0SRafał Miłecki }
92dd4544f0SRafał Miłecki 
93dd4544f0SRafał Miłecki static void bgmac_dma_tx_enable(struct bgmac *bgmac,
94dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
95dd4544f0SRafał Miłecki {
96dd4544f0SRafał Miłecki 	u32 ctl;
97dd4544f0SRafał Miłecki 
98dd4544f0SRafał Miłecki 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
9956ceecdeSHauke Mehrtens 	if (bgmac->core->id.rev >= 4) {
10056ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_TX_BL_MASK;
10156ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_TX_BL_128 << BGMAC_DMA_TX_BL_SHIFT;
10256ceecdeSHauke Mehrtens 
10356ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_TX_MR_MASK;
10456ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_TX_MR_2 << BGMAC_DMA_TX_MR_SHIFT;
10556ceecdeSHauke Mehrtens 
10656ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_TX_PC_MASK;
10756ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_TX_PC_16 << BGMAC_DMA_TX_PC_SHIFT;
10856ceecdeSHauke Mehrtens 
10956ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_TX_PT_MASK;
11056ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_TX_PT_8 << BGMAC_DMA_TX_PT_SHIFT;
11156ceecdeSHauke Mehrtens 	}
112dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_TX_ENABLE;
113dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
114dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
115dd4544f0SRafał Miłecki }
116dd4544f0SRafał Miłecki 
117dd4544f0SRafał Miłecki static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
118dd4544f0SRafał Miłecki 				    struct bgmac_dma_ring *ring,
119dd4544f0SRafał Miłecki 				    struct sk_buff *skb)
120dd4544f0SRafał Miłecki {
121dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
122dd4544f0SRafał Miłecki 	struct net_device *net_dev = bgmac->net_dev;
123dd4544f0SRafał Miłecki 	struct bgmac_dma_desc *dma_desc;
124dd4544f0SRafał Miłecki 	struct bgmac_slot_info *slot;
125dd4544f0SRafał Miłecki 	u32 ctl0, ctl1;
126dd4544f0SRafał Miłecki 	int free_slots;
127dd4544f0SRafał Miłecki 
128dd4544f0SRafał Miłecki 	if (skb->len > BGMAC_DESC_CTL1_LEN) {
129dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Too long skb (%d)\n", skb->len);
130dd4544f0SRafał Miłecki 		goto err_stop_drop;
131dd4544f0SRafał Miłecki 	}
132dd4544f0SRafał Miłecki 
133dd4544f0SRafał Miłecki 	if (ring->start <= ring->end)
134dd4544f0SRafał Miłecki 		free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
135dd4544f0SRafał Miłecki 	else
136dd4544f0SRafał Miłecki 		free_slots = ring->start - ring->end;
137dd4544f0SRafał Miłecki 	if (free_slots == 1) {
138dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
139dd4544f0SRafał Miłecki 		netif_stop_queue(net_dev);
140dd4544f0SRafał Miłecki 		return NETDEV_TX_BUSY;
141dd4544f0SRafał Miłecki 	}
142dd4544f0SRafał Miłecki 
143dd4544f0SRafał Miłecki 	slot = &ring->slots[ring->end];
144dd4544f0SRafał Miłecki 	slot->skb = skb;
145dd4544f0SRafał Miłecki 	slot->dma_addr = dma_map_single(dma_dev, skb->data, skb->len,
146dd4544f0SRafał Miłecki 					DMA_TO_DEVICE);
147dd4544f0SRafał Miłecki 	if (dma_mapping_error(dma_dev, slot->dma_addr)) {
148dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Mapping error of skb on ring 0x%X\n",
149dd4544f0SRafał Miłecki 			  ring->mmio_base);
150dd4544f0SRafał Miłecki 		goto err_stop_drop;
151dd4544f0SRafał Miłecki 	}
152dd4544f0SRafał Miłecki 
153dd4544f0SRafał Miłecki 	ctl0 = BGMAC_DESC_CTL0_IOC | BGMAC_DESC_CTL0_SOF | BGMAC_DESC_CTL0_EOF;
154dd4544f0SRafał Miłecki 	if (ring->end == ring->num_slots - 1)
155dd4544f0SRafał Miłecki 		ctl0 |= BGMAC_DESC_CTL0_EOT;
156dd4544f0SRafał Miłecki 	ctl1 = skb->len & BGMAC_DESC_CTL1_LEN;
157dd4544f0SRafał Miłecki 
158dd4544f0SRafał Miłecki 	dma_desc = ring->cpu_base;
159dd4544f0SRafał Miłecki 	dma_desc += ring->end;
160dd4544f0SRafał Miłecki 	dma_desc->addr_low = cpu_to_le32(lower_32_bits(slot->dma_addr));
161dd4544f0SRafał Miłecki 	dma_desc->addr_high = cpu_to_le32(upper_32_bits(slot->dma_addr));
162dd4544f0SRafał Miłecki 	dma_desc->ctl0 = cpu_to_le32(ctl0);
163dd4544f0SRafał Miłecki 	dma_desc->ctl1 = cpu_to_le32(ctl1);
164dd4544f0SRafał Miłecki 
16549a467b4SHauke Mehrtens 	netdev_sent_queue(net_dev, skb->len);
16649a467b4SHauke Mehrtens 
167dd4544f0SRafał Miłecki 	wmb();
168dd4544f0SRafał Miłecki 
169dd4544f0SRafał Miłecki 	/* Increase ring->end to point empty slot. We tell hardware the first
170dd4544f0SRafał Miłecki 	 * slot it should *not* read.
171dd4544f0SRafał Miłecki 	 */
172dd4544f0SRafał Miłecki 	if (++ring->end >= BGMAC_TX_RING_SLOTS)
173dd4544f0SRafał Miłecki 		ring->end = 0;
174dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
1759900303eSRafał Miłecki 		    ring->index_base +
176dd4544f0SRafał Miłecki 		    ring->end * sizeof(struct bgmac_dma_desc));
177dd4544f0SRafał Miłecki 
178dd4544f0SRafał Miłecki 	/* Always keep one slot free to allow detecting bugged calls. */
179dd4544f0SRafał Miłecki 	if (--free_slots == 1)
180dd4544f0SRafał Miłecki 		netif_stop_queue(net_dev);
181dd4544f0SRafał Miłecki 
182dd4544f0SRafał Miłecki 	return NETDEV_TX_OK;
183dd4544f0SRafał Miłecki 
184dd4544f0SRafał Miłecki err_stop_drop:
185dd4544f0SRafał Miłecki 	netif_stop_queue(net_dev);
186dd4544f0SRafał Miłecki 	dev_kfree_skb(skb);
187dd4544f0SRafał Miłecki 	return NETDEV_TX_OK;
188dd4544f0SRafał Miłecki }
189dd4544f0SRafał Miłecki 
190dd4544f0SRafał Miłecki /* Free transmitted packets */
191dd4544f0SRafał Miłecki static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
192dd4544f0SRafał Miłecki {
193dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
194dd4544f0SRafał Miłecki 	int empty_slot;
195dd4544f0SRafał Miłecki 	bool freed = false;
19649a467b4SHauke Mehrtens 	unsigned bytes_compl = 0, pkts_compl = 0;
197dd4544f0SRafał Miłecki 
198dd4544f0SRafał Miłecki 	/* The last slot that hardware didn't consume yet */
199dd4544f0SRafał Miłecki 	empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
200dd4544f0SRafał Miłecki 	empty_slot &= BGMAC_DMA_TX_STATDPTR;
2019900303eSRafał Miłecki 	empty_slot -= ring->index_base;
2029900303eSRafał Miłecki 	empty_slot &= BGMAC_DMA_TX_STATDPTR;
203dd4544f0SRafał Miłecki 	empty_slot /= sizeof(struct bgmac_dma_desc);
204dd4544f0SRafał Miłecki 
205dd4544f0SRafał Miłecki 	while (ring->start != empty_slot) {
206dd4544f0SRafał Miłecki 		struct bgmac_slot_info *slot = &ring->slots[ring->start];
207dd4544f0SRafał Miłecki 
208dd4544f0SRafał Miłecki 		if (slot->skb) {
209dd4544f0SRafał Miłecki 			/* Unmap no longer used buffer */
210dd4544f0SRafał Miłecki 			dma_unmap_single(dma_dev, slot->dma_addr,
211dd4544f0SRafał Miłecki 					 slot->skb->len, DMA_TO_DEVICE);
212dd4544f0SRafał Miłecki 			slot->dma_addr = 0;
213dd4544f0SRafał Miłecki 
21449a467b4SHauke Mehrtens 			bytes_compl += slot->skb->len;
21549a467b4SHauke Mehrtens 			pkts_compl++;
21649a467b4SHauke Mehrtens 
217dd4544f0SRafał Miłecki 			/* Free memory! :) */
218dd4544f0SRafał Miłecki 			dev_kfree_skb(slot->skb);
219dd4544f0SRafał Miłecki 			slot->skb = NULL;
220dd4544f0SRafał Miłecki 		} else {
221dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
222dd4544f0SRafał Miłecki 				  ring->start, ring->end);
223dd4544f0SRafał Miłecki 		}
224dd4544f0SRafał Miłecki 
225dd4544f0SRafał Miłecki 		if (++ring->start >= BGMAC_TX_RING_SLOTS)
226dd4544f0SRafał Miłecki 			ring->start = 0;
227dd4544f0SRafał Miłecki 		freed = true;
228dd4544f0SRafał Miłecki 	}
229dd4544f0SRafał Miłecki 
23049a467b4SHauke Mehrtens 	netdev_completed_queue(bgmac->net_dev, pkts_compl, bytes_compl);
23149a467b4SHauke Mehrtens 
232dd4544f0SRafał Miłecki 	if (freed && netif_queue_stopped(bgmac->net_dev))
233dd4544f0SRafał Miłecki 		netif_wake_queue(bgmac->net_dev);
234dd4544f0SRafał Miłecki }
235dd4544f0SRafał Miłecki 
236dd4544f0SRafał Miłecki static void bgmac_dma_rx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
237dd4544f0SRafał Miłecki {
238dd4544f0SRafał Miłecki 	if (!ring->mmio_base)
239dd4544f0SRafał Miłecki 		return;
240dd4544f0SRafał Miłecki 
241dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, 0);
242dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(bgmac->core,
243dd4544f0SRafał Miłecki 			      ring->mmio_base + BGMAC_DMA_RX_STATUS,
244dd4544f0SRafał Miłecki 			      BGMAC_DMA_RX_STAT, BGMAC_DMA_RX_STAT_DISABLED,
245dd4544f0SRafał Miłecki 			      10000))
246dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Reset of ring 0x%X RX failed\n",
247dd4544f0SRafał Miłecki 			  ring->mmio_base);
248dd4544f0SRafał Miłecki }
249dd4544f0SRafał Miłecki 
250dd4544f0SRafał Miłecki static void bgmac_dma_rx_enable(struct bgmac *bgmac,
251dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
252dd4544f0SRafał Miłecki {
253dd4544f0SRafał Miłecki 	u32 ctl;
254dd4544f0SRafał Miłecki 
255dd4544f0SRafał Miłecki 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL);
25656ceecdeSHauke Mehrtens 	if (bgmac->core->id.rev >= 4) {
25756ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_RX_BL_MASK;
25856ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;
25956ceecdeSHauke Mehrtens 
26056ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_RX_PC_MASK;
26156ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_RX_PC_8 << BGMAC_DMA_RX_PC_SHIFT;
26256ceecdeSHauke Mehrtens 
26356ceecdeSHauke Mehrtens 		ctl &= ~BGMAC_DMA_RX_PT_MASK;
26456ceecdeSHauke Mehrtens 		ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
26556ceecdeSHauke Mehrtens 	}
266dd4544f0SRafał Miłecki 	ctl &= BGMAC_DMA_RX_ADDREXT_MASK;
267dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_ENABLE;
268dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
269dd4544f0SRafał Miłecki 	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
270dd4544f0SRafał Miłecki 	ctl |= BGMAC_RX_FRAME_OFFSET << BGMAC_DMA_RX_FRAME_OFFSET_SHIFT;
271dd4544f0SRafał Miłecki 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, ctl);
272dd4544f0SRafał Miłecki }
273dd4544f0SRafał Miłecki 
274dd4544f0SRafał Miłecki static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
275dd4544f0SRafał Miłecki 				     struct bgmac_slot_info *slot)
276dd4544f0SRafał Miłecki {
277dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
278b757a62eSNathan Hintz 	struct sk_buff *skb;
279b757a62eSNathan Hintz 	dma_addr_t dma_addr;
280dd4544f0SRafał Miłecki 	struct bgmac_rx_header *rx;
281dd4544f0SRafał Miłecki 
282dd4544f0SRafał Miłecki 	/* Alloc skb */
283b757a62eSNathan Hintz 	skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
284b757a62eSNathan Hintz 	if (!skb)
285dd4544f0SRafał Miłecki 		return -ENOMEM;
286dd4544f0SRafał Miłecki 
287dd4544f0SRafał Miłecki 	/* Poison - if everything goes fine, hardware will overwrite it */
288b757a62eSNathan Hintz 	rx = (struct bgmac_rx_header *)skb->data;
289dd4544f0SRafał Miłecki 	rx->len = cpu_to_le16(0xdead);
290dd4544f0SRafał Miłecki 	rx->flags = cpu_to_le16(0xbeef);
291dd4544f0SRafał Miłecki 
292dd4544f0SRafał Miłecki 	/* Map skb for the DMA */
293b757a62eSNathan Hintz 	dma_addr = dma_map_single(dma_dev, skb->data,
294dd4544f0SRafał Miłecki 				  BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
295b757a62eSNathan Hintz 	if (dma_mapping_error(dma_dev, dma_addr)) {
296dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "DMA mapping error\n");
297b757a62eSNathan Hintz 		dev_kfree_skb(skb);
298dd4544f0SRafał Miłecki 		return -ENOMEM;
299dd4544f0SRafał Miłecki 	}
300b757a62eSNathan Hintz 
301b757a62eSNathan Hintz 	/* Update the slot */
302b757a62eSNathan Hintz 	slot->skb = skb;
303b757a62eSNathan Hintz 	slot->dma_addr = dma_addr;
304b757a62eSNathan Hintz 
305dd4544f0SRafał Miłecki 	return 0;
306dd4544f0SRafał Miłecki }
307dd4544f0SRafał Miłecki 
308d549c76bSRafał Miłecki static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
309d549c76bSRafał Miłecki 				    struct bgmac_dma_ring *ring, int desc_idx)
310d549c76bSRafał Miłecki {
311d549c76bSRafał Miłecki 	struct bgmac_dma_desc *dma_desc = ring->cpu_base + desc_idx;
312d549c76bSRafał Miłecki 	u32 ctl0 = 0, ctl1 = 0;
313d549c76bSRafał Miłecki 
314d549c76bSRafał Miłecki 	if (desc_idx == ring->num_slots - 1)
315d549c76bSRafał Miłecki 		ctl0 |= BGMAC_DESC_CTL0_EOT;
316d549c76bSRafał Miłecki 	ctl1 |= BGMAC_RX_BUF_SIZE & BGMAC_DESC_CTL1_LEN;
317d549c76bSRafał Miłecki 	/* Is there any BGMAC device that requires extension? */
318d549c76bSRafał Miłecki 	/* ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT) &
319d549c76bSRafał Miłecki 	 * B43_DMA64_DCTL1_ADDREXT_MASK;
320d549c76bSRafał Miłecki 	 */
321d549c76bSRafał Miłecki 
322d549c76bSRafał Miłecki 	dma_desc->addr_low = cpu_to_le32(lower_32_bits(ring->slots[desc_idx].dma_addr));
323d549c76bSRafał Miłecki 	dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr));
324d549c76bSRafał Miłecki 	dma_desc->ctl0 = cpu_to_le32(ctl0);
325d549c76bSRafał Miłecki 	dma_desc->ctl1 = cpu_to_le32(ctl1);
326d549c76bSRafał Miłecki }
327d549c76bSRafał Miłecki 
328dd4544f0SRafał Miłecki static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
329dd4544f0SRafał Miłecki 			     int weight)
330dd4544f0SRafał Miłecki {
331dd4544f0SRafał Miłecki 	u32 end_slot;
332dd4544f0SRafał Miłecki 	int handled = 0;
333dd4544f0SRafał Miłecki 
334dd4544f0SRafał Miłecki 	end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS);
335dd4544f0SRafał Miłecki 	end_slot &= BGMAC_DMA_RX_STATDPTR;
3369900303eSRafał Miłecki 	end_slot -= ring->index_base;
3379900303eSRafał Miłecki 	end_slot &= BGMAC_DMA_RX_STATDPTR;
338dd4544f0SRafał Miłecki 	end_slot /= sizeof(struct bgmac_dma_desc);
339dd4544f0SRafał Miłecki 
340dd4544f0SRafał Miłecki 	ring->end = end_slot;
341dd4544f0SRafał Miłecki 
342dd4544f0SRafał Miłecki 	while (ring->start != ring->end) {
343dd4544f0SRafał Miłecki 		struct device *dma_dev = bgmac->core->dma_dev;
344dd4544f0SRafał Miłecki 		struct bgmac_slot_info *slot = &ring->slots[ring->start];
345dd4544f0SRafał Miłecki 		struct sk_buff *skb = slot->skb;
346dd4544f0SRafał Miłecki 		struct bgmac_rx_header *rx;
347dd4544f0SRafał Miłecki 		u16 len, flags;
348dd4544f0SRafał Miłecki 
349dd4544f0SRafał Miłecki 		/* Unmap buffer to make it accessible to the CPU */
350dd4544f0SRafał Miłecki 		dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
351dd4544f0SRafał Miłecki 					BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
352dd4544f0SRafał Miłecki 
353dd4544f0SRafał Miłecki 		/* Get info from the header */
354dd4544f0SRafał Miłecki 		rx = (struct bgmac_rx_header *)skb->data;
355dd4544f0SRafał Miłecki 		len = le16_to_cpu(rx->len);
356dd4544f0SRafał Miłecki 		flags = le16_to_cpu(rx->flags);
357dd4544f0SRafał Miłecki 
35892b9ccd3SRafał Miłecki 		do {
35992b9ccd3SRafał Miłecki 			dma_addr_t old_dma_addr = slot->dma_addr;
36092b9ccd3SRafał Miłecki 			int err;
36192b9ccd3SRafał Miłecki 
362dd4544f0SRafał Miłecki 			/* Check for poison and drop or pass the packet */
363dd4544f0SRafał Miłecki 			if (len == 0xdead && flags == 0xbeef) {
364dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
365dd4544f0SRafał Miłecki 					  ring->start);
36692b9ccd3SRafał Miłecki 				dma_sync_single_for_device(dma_dev,
36792b9ccd3SRafał Miłecki 							   slot->dma_addr,
36892b9ccd3SRafał Miłecki 							   BGMAC_RX_BUF_SIZE,
36992b9ccd3SRafał Miłecki 							   DMA_FROM_DEVICE);
37092b9ccd3SRafał Miłecki 				break;
37192b9ccd3SRafał Miłecki 			}
37292b9ccd3SRafał Miłecki 
37302e71127SHauke Mehrtens 			/* Omit CRC. */
37402e71127SHauke Mehrtens 			len -= ETH_FCS_LEN;
37502e71127SHauke Mehrtens 
37692b9ccd3SRafał Miłecki 			/* Prepare new skb as replacement */
37792b9ccd3SRafał Miłecki 			err = bgmac_dma_rx_skb_for_slot(bgmac, slot);
37892b9ccd3SRafał Miłecki 			if (err) {
379dd4544f0SRafał Miłecki 				/* Poison the old skb */
380dd4544f0SRafał Miłecki 				rx->len = cpu_to_le16(0xdead);
381dd4544f0SRafał Miłecki 				rx->flags = cpu_to_le16(0xbeef);
382dd4544f0SRafał Miłecki 
38392b9ccd3SRafał Miłecki 				dma_sync_single_for_device(dma_dev,
38492b9ccd3SRafał Miłecki 							   slot->dma_addr,
38592b9ccd3SRafał Miłecki 							   BGMAC_RX_BUF_SIZE,
38692b9ccd3SRafał Miłecki 							   DMA_FROM_DEVICE);
38792b9ccd3SRafał Miłecki 				break;
38892b9ccd3SRafał Miłecki 			}
38992b9ccd3SRafał Miłecki 			bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
39092b9ccd3SRafał Miłecki 
39192b9ccd3SRafał Miłecki 			/* Unmap old skb, we'll pass it to the netfif */
39292b9ccd3SRafał Miłecki 			dma_unmap_single(dma_dev, old_dma_addr,
393dd4544f0SRafał Miłecki 					 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
394dd4544f0SRafał Miłecki 
39592b9ccd3SRafał Miłecki 			skb_put(skb, BGMAC_RX_FRAME_OFFSET + len);
39692b9ccd3SRafał Miłecki 			skb_pull(skb, BGMAC_RX_FRAME_OFFSET);
39792b9ccd3SRafał Miłecki 
39892b9ccd3SRafał Miłecki 			skb_checksum_none_assert(skb);
39992b9ccd3SRafał Miłecki 			skb->protocol = eth_type_trans(skb, bgmac->net_dev);
40092b9ccd3SRafał Miłecki 			netif_receive_skb(skb);
40192b9ccd3SRafał Miłecki 			handled++;
40292b9ccd3SRafał Miłecki 		} while (0);
40392b9ccd3SRafał Miłecki 
404dd4544f0SRafał Miłecki 		if (++ring->start >= BGMAC_RX_RING_SLOTS)
405dd4544f0SRafał Miłecki 			ring->start = 0;
406dd4544f0SRafał Miłecki 
407dd4544f0SRafał Miłecki 		if (handled >= weight) /* Should never be greater */
408dd4544f0SRafał Miłecki 			break;
409dd4544f0SRafał Miłecki 	}
410dd4544f0SRafał Miłecki 
411dd4544f0SRafał Miłecki 	return handled;
412dd4544f0SRafał Miłecki }
413dd4544f0SRafał Miłecki 
414dd4544f0SRafał Miłecki /* Does ring support unaligned addressing? */
415dd4544f0SRafał Miłecki static bool bgmac_dma_unaligned(struct bgmac *bgmac,
416dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring,
417dd4544f0SRafał Miłecki 				enum bgmac_dma_ring_type ring_type)
418dd4544f0SRafał Miłecki {
419dd4544f0SRafał Miłecki 	switch (ring_type) {
420dd4544f0SRafał Miłecki 	case BGMAC_DMA_RING_TX:
421dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
422dd4544f0SRafał Miłecki 			    0xff0);
423dd4544f0SRafał Miłecki 		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO))
424dd4544f0SRafał Miłecki 			return true;
425dd4544f0SRafał Miłecki 		break;
426dd4544f0SRafał Miłecki 	case BGMAC_DMA_RING_RX:
427dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
428dd4544f0SRafał Miłecki 			    0xff0);
429dd4544f0SRafał Miłecki 		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO))
430dd4544f0SRafał Miłecki 			return true;
431dd4544f0SRafał Miłecki 		break;
432dd4544f0SRafał Miłecki 	}
433dd4544f0SRafał Miłecki 	return false;
434dd4544f0SRafał Miłecki }
435dd4544f0SRafał Miłecki 
436dd4544f0SRafał Miłecki static void bgmac_dma_ring_free(struct bgmac *bgmac,
437dd4544f0SRafał Miłecki 				struct bgmac_dma_ring *ring)
438dd4544f0SRafał Miłecki {
439dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
440dd4544f0SRafał Miłecki 	struct bgmac_slot_info *slot;
441dd4544f0SRafał Miłecki 	int size;
442dd4544f0SRafał Miłecki 	int i;
443dd4544f0SRafał Miłecki 
444dd4544f0SRafał Miłecki 	for (i = 0; i < ring->num_slots; i++) {
445dd4544f0SRafał Miłecki 		slot = &ring->slots[i];
446dd4544f0SRafał Miłecki 		if (slot->skb) {
447dd4544f0SRafał Miłecki 			if (slot->dma_addr)
448dd4544f0SRafał Miłecki 				dma_unmap_single(dma_dev, slot->dma_addr,
449dd4544f0SRafał Miłecki 						 slot->skb->len, DMA_TO_DEVICE);
450dd4544f0SRafał Miłecki 			dev_kfree_skb(slot->skb);
451dd4544f0SRafał Miłecki 		}
452dd4544f0SRafał Miłecki 	}
453dd4544f0SRafał Miłecki 
454dd4544f0SRafał Miłecki 	if (ring->cpu_base) {
455dd4544f0SRafał Miłecki 		/* Free ring of descriptors */
456dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
457dd4544f0SRafał Miłecki 		dma_free_coherent(dma_dev, size, ring->cpu_base,
458dd4544f0SRafał Miłecki 				  ring->dma_base);
459dd4544f0SRafał Miłecki 	}
460dd4544f0SRafał Miłecki }
461dd4544f0SRafał Miłecki 
462dd4544f0SRafał Miłecki static void bgmac_dma_free(struct bgmac *bgmac)
463dd4544f0SRafał Miłecki {
464dd4544f0SRafał Miłecki 	int i;
465dd4544f0SRafał Miłecki 
466dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
467dd4544f0SRafał Miłecki 		bgmac_dma_ring_free(bgmac, &bgmac->tx_ring[i]);
468dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
469dd4544f0SRafał Miłecki 		bgmac_dma_ring_free(bgmac, &bgmac->rx_ring[i]);
470dd4544f0SRafał Miłecki }
471dd4544f0SRafał Miłecki 
472dd4544f0SRafał Miłecki static int bgmac_dma_alloc(struct bgmac *bgmac)
473dd4544f0SRafał Miłecki {
474dd4544f0SRafał Miłecki 	struct device *dma_dev = bgmac->core->dma_dev;
475dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
476dd4544f0SRafał Miłecki 	static const u16 ring_base[] = { BGMAC_DMA_BASE0, BGMAC_DMA_BASE1,
477dd4544f0SRafał Miłecki 					 BGMAC_DMA_BASE2, BGMAC_DMA_BASE3, };
478dd4544f0SRafał Miłecki 	int size; /* ring size: different for Tx and Rx */
479dd4544f0SRafał Miłecki 	int err;
480dd4544f0SRafał Miłecki 	int i;
481dd4544f0SRafał Miłecki 
482dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base));
483dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base));
484dd4544f0SRafał Miłecki 
485dd4544f0SRafał Miłecki 	if (!(bcma_aread32(bgmac->core, BCMA_IOST) & BCMA_IOST_DMA64)) {
486dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Core does not report 64-bit DMA\n");
487dd4544f0SRafał Miłecki 		return -ENOTSUPP;
488dd4544f0SRafał Miłecki 	}
489dd4544f0SRafał Miłecki 
490dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
491dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[i];
492dd4544f0SRafał Miłecki 		ring->num_slots = BGMAC_TX_RING_SLOTS;
493dd4544f0SRafał Miłecki 		ring->mmio_base = ring_base[i];
494dd4544f0SRafał Miłecki 
495dd4544f0SRafał Miłecki 		/* Alloc ring of descriptors */
496dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
497dd4544f0SRafał Miłecki 		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
498dd4544f0SRafał Miłecki 						     &ring->dma_base,
499dd4544f0SRafał Miłecki 						     GFP_KERNEL);
500dd4544f0SRafał Miłecki 		if (!ring->cpu_base) {
501dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Allocation of TX ring 0x%X failed\n",
502dd4544f0SRafał Miłecki 				  ring->mmio_base);
503dd4544f0SRafał Miłecki 			goto err_dma_free;
504dd4544f0SRafał Miłecki 		}
505dd4544f0SRafał Miłecki 
5069900303eSRafał Miłecki 		ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
5079900303eSRafał Miłecki 						      BGMAC_DMA_RING_TX);
5089900303eSRafał Miłecki 		if (ring->unaligned)
5099900303eSRafał Miłecki 			ring->index_base = lower_32_bits(ring->dma_base);
5109900303eSRafał Miłecki 		else
5119900303eSRafał Miłecki 			ring->index_base = 0;
5129900303eSRafał Miłecki 
513dd4544f0SRafał Miłecki 		/* No need to alloc TX slots yet */
514dd4544f0SRafał Miłecki 	}
515dd4544f0SRafał Miłecki 
516dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
51770a737b7SRafał Miłecki 		int j;
51870a737b7SRafał Miłecki 
519dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[i];
520dd4544f0SRafał Miłecki 		ring->num_slots = BGMAC_RX_RING_SLOTS;
521dd4544f0SRafał Miłecki 		ring->mmio_base = ring_base[i];
522dd4544f0SRafał Miłecki 
523dd4544f0SRafał Miłecki 		/* Alloc ring of descriptors */
524dd4544f0SRafał Miłecki 		size = ring->num_slots * sizeof(struct bgmac_dma_desc);
525dd4544f0SRafał Miłecki 		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
526dd4544f0SRafał Miłecki 						     &ring->dma_base,
527dd4544f0SRafał Miłecki 						     GFP_KERNEL);
528dd4544f0SRafał Miłecki 		if (!ring->cpu_base) {
529dd4544f0SRafał Miłecki 			bgmac_err(bgmac, "Allocation of RX ring 0x%X failed\n",
530dd4544f0SRafał Miłecki 				  ring->mmio_base);
531dd4544f0SRafał Miłecki 			err = -ENOMEM;
532dd4544f0SRafał Miłecki 			goto err_dma_free;
533dd4544f0SRafał Miłecki 		}
534dd4544f0SRafał Miłecki 
5359900303eSRafał Miłecki 		ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
5369900303eSRafał Miłecki 						      BGMAC_DMA_RING_RX);
5379900303eSRafał Miłecki 		if (ring->unaligned)
5389900303eSRafał Miłecki 			ring->index_base = lower_32_bits(ring->dma_base);
5399900303eSRafał Miłecki 		else
5409900303eSRafał Miłecki 			ring->index_base = 0;
5419900303eSRafał Miłecki 
542dd4544f0SRafał Miłecki 		/* Alloc RX slots */
54370a737b7SRafał Miłecki 		for (j = 0; j < ring->num_slots; j++) {
54470a737b7SRafał Miłecki 			err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
545dd4544f0SRafał Miłecki 			if (err) {
546dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Can't allocate skb for slot in RX ring\n");
547dd4544f0SRafał Miłecki 				goto err_dma_free;
548dd4544f0SRafał Miłecki 			}
549dd4544f0SRafał Miłecki 		}
550dd4544f0SRafał Miłecki 	}
551dd4544f0SRafał Miłecki 
552dd4544f0SRafał Miłecki 	return 0;
553dd4544f0SRafał Miłecki 
554dd4544f0SRafał Miłecki err_dma_free:
555dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
556dd4544f0SRafał Miłecki 	return -ENOMEM;
557dd4544f0SRafał Miłecki }
558dd4544f0SRafał Miłecki 
559dd4544f0SRafał Miłecki static void bgmac_dma_init(struct bgmac *bgmac)
560dd4544f0SRafał Miłecki {
561dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
562dd4544f0SRafał Miłecki 	int i;
563dd4544f0SRafał Miłecki 
564dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
565dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[i];
566dd4544f0SRafał Miłecki 
5679900303eSRafał Miłecki 		if (!ring->unaligned)
568dd4544f0SRafał Miłecki 			bgmac_dma_tx_enable(bgmac, ring);
569dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
570dd4544f0SRafał Miłecki 			    lower_32_bits(ring->dma_base));
571dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI,
572dd4544f0SRafał Miłecki 			    upper_32_bits(ring->dma_base));
5739900303eSRafał Miłecki 		if (ring->unaligned)
5749900303eSRafał Miłecki 			bgmac_dma_tx_enable(bgmac, ring);
575dd4544f0SRafał Miłecki 
576dd4544f0SRafał Miłecki 		ring->start = 0;
577dd4544f0SRafał Miłecki 		ring->end = 0;	/* Points the slot that should *not* be read */
578dd4544f0SRafał Miłecki 	}
579dd4544f0SRafał Miłecki 
580dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
58170a737b7SRafał Miłecki 		int j;
58270a737b7SRafał Miłecki 
583dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[i];
584dd4544f0SRafał Miłecki 
5859900303eSRafał Miłecki 		if (!ring->unaligned)
586dd4544f0SRafał Miłecki 			bgmac_dma_rx_enable(bgmac, ring);
587dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
588dd4544f0SRafał Miłecki 			    lower_32_bits(ring->dma_base));
589dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI,
590dd4544f0SRafał Miłecki 			    upper_32_bits(ring->dma_base));
5919900303eSRafał Miłecki 		if (ring->unaligned)
5929900303eSRafał Miłecki 			bgmac_dma_rx_enable(bgmac, ring);
593dd4544f0SRafał Miłecki 
594d549c76bSRafał Miłecki 		for (j = 0; j < ring->num_slots; j++)
595d549c76bSRafał Miłecki 			bgmac_dma_rx_setup_desc(bgmac, ring, j);
596dd4544f0SRafał Miłecki 
597dd4544f0SRafał Miłecki 		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
5989900303eSRafał Miłecki 			    ring->index_base +
599dd4544f0SRafał Miłecki 			    ring->num_slots * sizeof(struct bgmac_dma_desc));
600dd4544f0SRafał Miłecki 
601dd4544f0SRafał Miłecki 		ring->start = 0;
602dd4544f0SRafał Miłecki 		ring->end = 0;
603dd4544f0SRafał Miłecki 	}
604dd4544f0SRafał Miłecki }
605dd4544f0SRafał Miłecki 
606dd4544f0SRafał Miłecki /**************************************************
607dd4544f0SRafał Miłecki  * PHY ops
608dd4544f0SRafał Miłecki  **************************************************/
609dd4544f0SRafał Miłecki 
610217a55a3SRafał Miłecki static u16 bgmac_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg)
611dd4544f0SRafał Miłecki {
612dd4544f0SRafał Miłecki 	struct bcma_device *core;
613dd4544f0SRafał Miłecki 	u16 phy_access_addr;
614dd4544f0SRafał Miłecki 	u16 phy_ctl_addr;
615dd4544f0SRafał Miłecki 	u32 tmp;
616dd4544f0SRafał Miłecki 
617dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK);
618dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK);
619dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT);
620dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK);
621dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT);
622dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE);
623dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START);
624dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK);
625dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK);
626dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
627dd4544f0SRafał Miłecki 	BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);
628dd4544f0SRafał Miłecki 
629dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
630dd4544f0SRafał Miłecki 		core = bgmac->core->bus->drv_gmac_cmn.core;
631dd4544f0SRafał Miłecki 		phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
632dd4544f0SRafał Miłecki 		phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
633dd4544f0SRafał Miłecki 	} else {
634dd4544f0SRafał Miłecki 		core = bgmac->core;
635dd4544f0SRafał Miłecki 		phy_access_addr = BGMAC_PHY_ACCESS;
636dd4544f0SRafał Miłecki 		phy_ctl_addr = BGMAC_PHY_CNTL;
637dd4544f0SRafał Miłecki 	}
638dd4544f0SRafał Miłecki 
639dd4544f0SRafał Miłecki 	tmp = bcma_read32(core, phy_ctl_addr);
640dd4544f0SRafał Miłecki 	tmp &= ~BGMAC_PC_EPA_MASK;
641dd4544f0SRafał Miłecki 	tmp |= phyaddr;
642dd4544f0SRafał Miłecki 	bcma_write32(core, phy_ctl_addr, tmp);
643dd4544f0SRafał Miłecki 
644dd4544f0SRafał Miłecki 	tmp = BGMAC_PA_START;
645dd4544f0SRafał Miłecki 	tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
646dd4544f0SRafał Miłecki 	tmp |= reg << BGMAC_PA_REG_SHIFT;
647dd4544f0SRafał Miłecki 	bcma_write32(core, phy_access_addr, tmp);
648dd4544f0SRafał Miłecki 
649dd4544f0SRafał Miłecki 	if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) {
650dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Reading PHY %d register 0x%X failed\n",
651dd4544f0SRafał Miłecki 			  phyaddr, reg);
652dd4544f0SRafał Miłecki 		return 0xffff;
653dd4544f0SRafał Miłecki 	}
654dd4544f0SRafał Miłecki 
655dd4544f0SRafał Miłecki 	return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK;
656dd4544f0SRafał Miłecki }
657dd4544f0SRafał Miłecki 
658dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
659217a55a3SRafał Miłecki static int bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value)
660dd4544f0SRafał Miłecki {
661dd4544f0SRafał Miłecki 	struct bcma_device *core;
662dd4544f0SRafał Miłecki 	u16 phy_access_addr;
663dd4544f0SRafał Miłecki 	u16 phy_ctl_addr;
664dd4544f0SRafał Miłecki 	u32 tmp;
665dd4544f0SRafał Miłecki 
666dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
667dd4544f0SRafał Miłecki 		core = bgmac->core->bus->drv_gmac_cmn.core;
668dd4544f0SRafał Miłecki 		phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
669dd4544f0SRafał Miłecki 		phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
670dd4544f0SRafał Miłecki 	} else {
671dd4544f0SRafał Miłecki 		core = bgmac->core;
672dd4544f0SRafał Miłecki 		phy_access_addr = BGMAC_PHY_ACCESS;
673dd4544f0SRafał Miłecki 		phy_ctl_addr = BGMAC_PHY_CNTL;
674dd4544f0SRafał Miłecki 	}
675dd4544f0SRafał Miłecki 
676dd4544f0SRafał Miłecki 	tmp = bcma_read32(core, phy_ctl_addr);
677dd4544f0SRafał Miłecki 	tmp &= ~BGMAC_PC_EPA_MASK;
678dd4544f0SRafał Miłecki 	tmp |= phyaddr;
679dd4544f0SRafał Miłecki 	bcma_write32(core, phy_ctl_addr, tmp);
680dd4544f0SRafał Miłecki 
681dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
682dd4544f0SRafał Miłecki 	if (bgmac_read(bgmac, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
683dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Error setting MDIO int\n");
684dd4544f0SRafał Miłecki 
685dd4544f0SRafał Miłecki 	tmp = BGMAC_PA_START;
686dd4544f0SRafał Miłecki 	tmp |= BGMAC_PA_WRITE;
687dd4544f0SRafał Miłecki 	tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
688dd4544f0SRafał Miłecki 	tmp |= reg << BGMAC_PA_REG_SHIFT;
689dd4544f0SRafał Miłecki 	tmp |= value;
690dd4544f0SRafał Miłecki 	bcma_write32(core, phy_access_addr, tmp);
691dd4544f0SRafał Miłecki 
692217a55a3SRafał Miłecki 	if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) {
693dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Writing to PHY %d register 0x%X failed\n",
694dd4544f0SRafał Miłecki 			  phyaddr, reg);
695217a55a3SRafał Miłecki 		return -ETIMEDOUT;
696217a55a3SRafał Miłecki 	}
697217a55a3SRafał Miłecki 
698217a55a3SRafał Miłecki 	return 0;
699dd4544f0SRafał Miłecki }
700dd4544f0SRafał Miłecki 
701dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
702dd4544f0SRafał Miłecki static void bgmac_phy_init(struct bgmac *bgmac)
703dd4544f0SRafał Miłecki {
704dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
705dd4544f0SRafał Miłecki 	struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
706dd4544f0SRafał Miłecki 	u8 i;
707dd4544f0SRafał Miłecki 
708dd4544f0SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM5356) {
709dd4544f0SRafał Miłecki 		for (i = 0; i < 5; i++) {
710dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x008b);
711dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x15, 0x0100);
712dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
713dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x12, 0x2aaa);
714dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
715dd4544f0SRafał Miłecki 		}
716dd4544f0SRafał Miłecki 	}
717dd4544f0SRafał Miłecki 	if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
718dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
719dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
720dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
721dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
722dd4544f0SRafał Miłecki 		for (i = 0; i < 5; i++) {
723dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
724dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x5284);
725dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
726dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x0010);
727dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
728dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x5296);
729dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x1073);
730dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x9073);
731dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x16, 0x52b6);
732dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x17, 0x9273);
733dd4544f0SRafał Miłecki 			bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
734dd4544f0SRafał Miłecki 		}
735dd4544f0SRafał Miłecki 	}
736dd4544f0SRafał Miłecki }
737dd4544f0SRafał Miłecki 
738dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
739dd4544f0SRafał Miłecki static void bgmac_phy_reset(struct bgmac *bgmac)
740dd4544f0SRafał Miłecki {
741dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
742dd4544f0SRafał Miłecki 		return;
743dd4544f0SRafał Miłecki 
7445322dbf0SRafał Miłecki 	bgmac_phy_write(bgmac, bgmac->phyaddr, MII_BMCR, BMCR_RESET);
745dd4544f0SRafał Miłecki 	udelay(100);
7465322dbf0SRafał Miłecki 	if (bgmac_phy_read(bgmac, bgmac->phyaddr, MII_BMCR) & BMCR_RESET)
747dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "PHY reset failed\n");
748dd4544f0SRafał Miłecki 	bgmac_phy_init(bgmac);
749dd4544f0SRafał Miłecki }
750dd4544f0SRafał Miłecki 
751dd4544f0SRafał Miłecki /**************************************************
752dd4544f0SRafał Miłecki  * Chip ops
753dd4544f0SRafał Miłecki  **************************************************/
754dd4544f0SRafał Miłecki 
755dd4544f0SRafał Miłecki /* TODO: can we just drop @force? Can we don't reset MAC at all if there is
756dd4544f0SRafał Miłecki  * nothing to change? Try if after stabilizng driver.
757dd4544f0SRafał Miłecki  */
758dd4544f0SRafał Miłecki static void bgmac_cmdcfg_maskset(struct bgmac *bgmac, u32 mask, u32 set,
759dd4544f0SRafał Miłecki 				 bool force)
760dd4544f0SRafał Miłecki {
761dd4544f0SRafał Miłecki 	u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
762dd4544f0SRafał Miłecki 	u32 new_val = (cmdcfg & mask) | set;
763dd4544f0SRafał Miłecki 
76448e07fbeSHauke Mehrtens 	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR(bgmac->core->id.rev));
765dd4544f0SRafał Miłecki 	udelay(2);
766dd4544f0SRafał Miłecki 
767dd4544f0SRafał Miłecki 	if (new_val != cmdcfg || force)
768dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_CMDCFG, new_val);
769dd4544f0SRafał Miłecki 
77048e07fbeSHauke Mehrtens 	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR(bgmac->core->id.rev));
771dd4544f0SRafał Miłecki 	udelay(2);
772dd4544f0SRafał Miłecki }
773dd4544f0SRafał Miłecki 
7744e209001SHauke Mehrtens static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr)
7754e209001SHauke Mehrtens {
7764e209001SHauke Mehrtens 	u32 tmp;
7774e209001SHauke Mehrtens 
7784e209001SHauke Mehrtens 	tmp = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
7794e209001SHauke Mehrtens 	bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
7804e209001SHauke Mehrtens 	tmp = (addr[4] << 8) | addr[5];
7814e209001SHauke Mehrtens 	bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
7824e209001SHauke Mehrtens }
7834e209001SHauke Mehrtens 
784c6edfe10SHauke Mehrtens static void bgmac_set_rx_mode(struct net_device *net_dev)
785c6edfe10SHauke Mehrtens {
786c6edfe10SHauke Mehrtens 	struct bgmac *bgmac = netdev_priv(net_dev);
787c6edfe10SHauke Mehrtens 
788c6edfe10SHauke Mehrtens 	if (net_dev->flags & IFF_PROMISC)
789e9ba1039SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, true);
790c6edfe10SHauke Mehrtens 	else
791e9ba1039SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, true);
792c6edfe10SHauke Mehrtens }
793c6edfe10SHauke Mehrtens 
794dd4544f0SRafał Miłecki #if 0 /* We don't use that regs yet */
795dd4544f0SRafał Miłecki static void bgmac_chip_stats_update(struct bgmac *bgmac)
796dd4544f0SRafał Miłecki {
797dd4544f0SRafał Miłecki 	int i;
798dd4544f0SRafał Miłecki 
799dd4544f0SRafał Miłecki 	if (bgmac->core->id.id != BCMA_CORE_4706_MAC_GBIT) {
800dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
801dd4544f0SRafał Miłecki 			bgmac->mib_tx_regs[i] =
802dd4544f0SRafał Miłecki 				bgmac_read(bgmac,
803dd4544f0SRafał Miłecki 					   BGMAC_TX_GOOD_OCTETS + (i * 4));
804dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
805dd4544f0SRafał Miłecki 			bgmac->mib_rx_regs[i] =
806dd4544f0SRafał Miłecki 				bgmac_read(bgmac,
807dd4544f0SRafał Miłecki 					   BGMAC_RX_GOOD_OCTETS + (i * 4));
808dd4544f0SRafał Miłecki 	}
809dd4544f0SRafał Miłecki 
810dd4544f0SRafał Miłecki 	/* TODO: what else? how to handle BCM4706? Specs are needed */
811dd4544f0SRafał Miłecki }
812dd4544f0SRafał Miłecki #endif
813dd4544f0SRafał Miłecki 
814dd4544f0SRafał Miłecki static void bgmac_clear_mib(struct bgmac *bgmac)
815dd4544f0SRafał Miłecki {
816dd4544f0SRafał Miłecki 	int i;
817dd4544f0SRafał Miłecki 
818dd4544f0SRafał Miłecki 	if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT)
819dd4544f0SRafał Miłecki 		return;
820dd4544f0SRafał Miłecki 
821dd4544f0SRafał Miłecki 	bgmac_set(bgmac, BGMAC_DEV_CTL, BGMAC_DC_MROR);
822dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
823dd4544f0SRafał Miłecki 		bgmac_read(bgmac, BGMAC_TX_GOOD_OCTETS + (i * 4));
824dd4544f0SRafał Miłecki 	for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
825dd4544f0SRafał Miłecki 		bgmac_read(bgmac, BGMAC_RX_GOOD_OCTETS + (i * 4));
826dd4544f0SRafał Miłecki }
827dd4544f0SRafał Miłecki 
828dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_speed */
8295824d2d1SRafał Miłecki static void bgmac_mac_speed(struct bgmac *bgmac)
830dd4544f0SRafał Miłecki {
831dd4544f0SRafał Miłecki 	u32 mask = ~(BGMAC_CMDCFG_ES_MASK | BGMAC_CMDCFG_HD);
832dd4544f0SRafał Miłecki 	u32 set = 0;
833dd4544f0SRafał Miłecki 
8345824d2d1SRafał Miłecki 	switch (bgmac->mac_speed) {
8355824d2d1SRafał Miłecki 	case SPEED_10:
836dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_10;
8375824d2d1SRafał Miłecki 		break;
8385824d2d1SRafał Miłecki 	case SPEED_100:
839dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_100;
8405824d2d1SRafał Miłecki 		break;
8415824d2d1SRafał Miłecki 	case SPEED_1000:
842dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_ES_1000;
8435824d2d1SRafał Miłecki 		break;
8446df4aff9SHauke Mehrtens 	case SPEED_2500:
8456df4aff9SHauke Mehrtens 		set |= BGMAC_CMDCFG_ES_2500;
8466df4aff9SHauke Mehrtens 		break;
8475824d2d1SRafał Miłecki 	default:
8485824d2d1SRafał Miłecki 		bgmac_err(bgmac, "Unsupported speed: %d\n", bgmac->mac_speed);
8495824d2d1SRafał Miłecki 	}
8505824d2d1SRafał Miłecki 
8515824d2d1SRafał Miłecki 	if (bgmac->mac_duplex == DUPLEX_HALF)
852dd4544f0SRafał Miłecki 		set |= BGMAC_CMDCFG_HD;
8535824d2d1SRafał Miłecki 
854dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, mask, set, true);
855dd4544f0SRafał Miłecki }
856dd4544f0SRafał Miłecki 
857dd4544f0SRafał Miłecki static void bgmac_miiconfig(struct bgmac *bgmac)
858dd4544f0SRafał Miłecki {
8596df4aff9SHauke Mehrtens 	struct bcma_device *core = bgmac->core;
8606df4aff9SHauke Mehrtens 	struct bcma_chipinfo *ci = &core->bus->chipinfo;
8616df4aff9SHauke Mehrtens 	u8 imode;
8626df4aff9SHauke Mehrtens 
8636df4aff9SHauke Mehrtens 	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
8646df4aff9SHauke Mehrtens 	    ci->id == BCMA_CHIP_ID_BCM53018) {
8656df4aff9SHauke Mehrtens 		bcma_awrite32(core, BCMA_IOCTL,
8666df4aff9SHauke Mehrtens 			      bcma_aread32(core, BCMA_IOCTL) | 0x40 |
8676df4aff9SHauke Mehrtens 			      BGMAC_BCMA_IOCTL_SW_CLKEN);
8686df4aff9SHauke Mehrtens 		bgmac->mac_speed = SPEED_2500;
8696df4aff9SHauke Mehrtens 		bgmac->mac_duplex = DUPLEX_FULL;
8706df4aff9SHauke Mehrtens 		bgmac_mac_speed(bgmac);
8716df4aff9SHauke Mehrtens 	} else {
8726df4aff9SHauke Mehrtens 		imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) &
8736df4aff9SHauke Mehrtens 			BGMAC_DS_MM_MASK) >> BGMAC_DS_MM_SHIFT;
874dd4544f0SRafał Miłecki 		if (imode == 0 || imode == 1) {
8755824d2d1SRafał Miłecki 			bgmac->mac_speed = SPEED_100;
8765824d2d1SRafał Miłecki 			bgmac->mac_duplex = DUPLEX_FULL;
8775824d2d1SRafał Miłecki 			bgmac_mac_speed(bgmac);
878dd4544f0SRafał Miłecki 		}
879dd4544f0SRafał Miłecki 	}
8806df4aff9SHauke Mehrtens }
881dd4544f0SRafał Miłecki 
882dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipreset */
883dd4544f0SRafał Miłecki static void bgmac_chip_reset(struct bgmac *bgmac)
884dd4544f0SRafał Miłecki {
885dd4544f0SRafał Miłecki 	struct bcma_device *core = bgmac->core;
886dd4544f0SRafał Miłecki 	struct bcma_bus *bus = core->bus;
887dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bus->chipinfo;
8886df4aff9SHauke Mehrtens 	u32 flags;
889dd4544f0SRafał Miłecki 	u32 iost;
890dd4544f0SRafał Miłecki 	int i;
891dd4544f0SRafał Miłecki 
892dd4544f0SRafał Miłecki 	if (bcma_core_is_enabled(core)) {
893dd4544f0SRafał Miłecki 		if (!bgmac->stats_grabbed) {
894dd4544f0SRafał Miłecki 			/* bgmac_chip_stats_update(bgmac); */
895dd4544f0SRafał Miłecki 			bgmac->stats_grabbed = true;
896dd4544f0SRafał Miłecki 		}
897dd4544f0SRafał Miłecki 
898dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
899dd4544f0SRafał Miłecki 			bgmac_dma_tx_reset(bgmac, &bgmac->tx_ring[i]);
900dd4544f0SRafał Miłecki 
901dd4544f0SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
902dd4544f0SRafał Miłecki 		udelay(1);
903dd4544f0SRafał Miłecki 
904dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
905dd4544f0SRafał Miłecki 			bgmac_dma_rx_reset(bgmac, &bgmac->rx_ring[i]);
906dd4544f0SRafał Miłecki 
907dd4544f0SRafał Miłecki 		/* TODO: Clear software multicast filter list */
908dd4544f0SRafał Miłecki 	}
909dd4544f0SRafał Miłecki 
910dd4544f0SRafał Miłecki 	iost = bcma_aread32(core, BCMA_IOST);
9111a0ab767SRafał Miłecki 	if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
912dd4544f0SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) ||
9131a0ab767SRafał Miłecki 	    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188))
914dd4544f0SRafał Miłecki 		iost &= ~BGMAC_BCMA_IOST_ATTACHED;
915dd4544f0SRafał Miłecki 
9166df4aff9SHauke Mehrtens 	/* 3GMAC: for BCM4707, only do core reset at bgmac_probe() */
9176df4aff9SHauke Mehrtens 	if (ci->id != BCMA_CHIP_ID_BCM4707) {
9186df4aff9SHauke Mehrtens 		flags = 0;
919dd4544f0SRafał Miłecki 		if (iost & BGMAC_BCMA_IOST_ATTACHED) {
920dd4544f0SRafał Miłecki 			flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
921dd4544f0SRafał Miłecki 			if (!bgmac->has_robosw)
922dd4544f0SRafał Miłecki 				flags |= BGMAC_BCMA_IOCTL_SW_RESET;
923dd4544f0SRafał Miłecki 		}
924dd4544f0SRafał Miłecki 		bcma_core_enable(core, flags);
9256df4aff9SHauke Mehrtens 	}
926dd4544f0SRafał Miłecki 
9276df4aff9SHauke Mehrtens 	/* Request Misc PLL for corerev > 2 */
9286df4aff9SHauke Mehrtens 	if (core->id.rev > 2 &&
9296df4aff9SHauke Mehrtens 	    ci->id != BCMA_CHIP_ID_BCM4707 &&
9306df4aff9SHauke Mehrtens 	    ci->id != BCMA_CHIP_ID_BCM53018) {
9311a0ab767SRafał Miłecki 		bgmac_set(bgmac, BCMA_CLKCTLST,
9321a0ab767SRafał Miłecki 			  BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ);
9331a0ab767SRafał Miłecki 		bgmac_wait_value(bgmac->core, BCMA_CLKCTLST,
9341a0ab767SRafał Miłecki 				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
9351a0ab767SRafał Miłecki 				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
936dd4544f0SRafał Miłecki 				 1000);
937dd4544f0SRafał Miłecki 	}
938dd4544f0SRafał Miłecki 
9391a0ab767SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM5357 ||
9401a0ab767SRafał Miłecki 	    ci->id == BCMA_CHIP_ID_BCM4749 ||
941dd4544f0SRafał Miłecki 	    ci->id == BCMA_CHIP_ID_BCM53572) {
942dd4544f0SRafał Miłecki 		struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
943dd4544f0SRafał Miłecki 		u8 et_swtype = 0;
944dd4544f0SRafał Miłecki 		u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY |
9456a391e7bSRafał Miłecki 			     BGMAC_CHIPCTL_1_IF_TYPE_MII;
9463647268dSHauke Mehrtens 		char buf[4];
947dd4544f0SRafał Miłecki 
9483647268dSHauke Mehrtens 		if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
949dd4544f0SRafał Miłecki 			if (kstrtou8(buf, 0, &et_swtype))
950dd4544f0SRafał Miłecki 				bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
951dd4544f0SRafał Miłecki 					  buf);
952dd4544f0SRafał Miłecki 			et_swtype &= 0x0f;
953dd4544f0SRafał Miłecki 			et_swtype <<= 4;
954dd4544f0SRafał Miłecki 			sw_type = et_swtype;
9551a0ab767SRafał Miłecki 		} else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358) {
956dd4544f0SRafał Miłecki 			sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
9571a0ab767SRafał Miłecki 		} else if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
9581a0ab767SRafał Miłecki 			   (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) ||
9591a0ab767SRafał Miłecki 			   (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
960b5a4c2f3SHauke Mehrtens 			sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
961b5a4c2f3SHauke Mehrtens 				  BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
962dd4544f0SRafał Miłecki 		}
963dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(cc, 1,
964dd4544f0SRafał Miłecki 					    ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
965dd4544f0SRafał Miłecki 					      BGMAC_CHIPCTL_1_SW_TYPE_MASK),
966dd4544f0SRafał Miłecki 					    sw_type);
967dd4544f0SRafał Miłecki 	}
968dd4544f0SRafał Miłecki 
969dd4544f0SRafał Miłecki 	if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
970dd4544f0SRafał Miłecki 		bcma_awrite32(core, BCMA_IOCTL,
971dd4544f0SRafał Miłecki 			      bcma_aread32(core, BCMA_IOCTL) &
972dd4544f0SRafał Miłecki 			      ~BGMAC_BCMA_IOCTL_SW_RESET);
973dd4544f0SRafał Miłecki 
974dd4544f0SRafał Miłecki 	/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_reset
975dd4544f0SRafał Miłecki 	 * Specs don't say about using BGMAC_CMDCFG_SR, but in this routine
976dd4544f0SRafał Miłecki 	 * BGMAC_CMDCFG is read _after_ putting chip in a reset. So it has to
977dd4544f0SRafał Miłecki 	 * be keps until taking MAC out of the reset.
978dd4544f0SRafał Miłecki 	 */
979dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac,
980dd4544f0SRafał Miłecki 			     ~(BGMAC_CMDCFG_TE |
981dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RE |
982dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RPI |
983dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_TAI |
984dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_HD |
985dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_ML |
986dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_CFE |
987dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RL |
988dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_RED |
989dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PE |
990dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_TPI |
991dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PAD_EN |
992dd4544f0SRafał Miłecki 			       BGMAC_CMDCFG_PF),
993dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_PROM |
994dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_NLC |
995dd4544f0SRafał Miłecki 			     BGMAC_CMDCFG_CFE |
99648e07fbeSHauke Mehrtens 			     BGMAC_CMDCFG_SR(core->id.rev),
997dd4544f0SRafał Miłecki 			     false);
998d469962fSRafał Miłecki 	bgmac->mac_speed = SPEED_UNKNOWN;
999d469962fSRafał Miłecki 	bgmac->mac_duplex = DUPLEX_UNKNOWN;
1000dd4544f0SRafał Miłecki 
1001dd4544f0SRafał Miłecki 	bgmac_clear_mib(bgmac);
1002dd4544f0SRafał Miłecki 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT)
1003dd4544f0SRafał Miłecki 		bcma_maskset32(bgmac->cmn, BCMA_GMAC_CMN_PHY_CTL, ~0,
1004dd4544f0SRafał Miłecki 			       BCMA_GMAC_CMN_PC_MTE);
1005dd4544f0SRafał Miłecki 	else
1006dd4544f0SRafał Miłecki 		bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE);
1007dd4544f0SRafał Miłecki 	bgmac_miiconfig(bgmac);
1008dd4544f0SRafał Miłecki 	bgmac_phy_init(bgmac);
1009dd4544f0SRafał Miłecki 
101049a467b4SHauke Mehrtens 	netdev_reset_queue(bgmac->net_dev);
101149a467b4SHauke Mehrtens 
1012dd4544f0SRafał Miłecki 	bgmac->int_status = 0;
1013dd4544f0SRafał Miłecki }
1014dd4544f0SRafał Miłecki 
1015dd4544f0SRafał Miłecki static void bgmac_chip_intrs_on(struct bgmac *bgmac)
1016dd4544f0SRafał Miłecki {
1017dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_MASK, bgmac->int_mask);
1018dd4544f0SRafał Miłecki }
1019dd4544f0SRafał Miłecki 
1020dd4544f0SRafał Miłecki static void bgmac_chip_intrs_off(struct bgmac *bgmac)
1021dd4544f0SRafał Miłecki {
1022dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_MASK, 0);
10234160815fSNathan Hintz 	bgmac_read(bgmac, BGMAC_INT_MASK);
1024dd4544f0SRafał Miłecki }
1025dd4544f0SRafał Miłecki 
1026dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_enable */
1027dd4544f0SRafał Miłecki static void bgmac_enable(struct bgmac *bgmac)
1028dd4544f0SRafał Miłecki {
1029dd4544f0SRafał Miłecki 	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
1030dd4544f0SRafał Miłecki 	u32 cmdcfg;
1031dd4544f0SRafał Miłecki 	u32 mode;
1032dd4544f0SRafał Miłecki 	u32 rxq_ctl;
1033dd4544f0SRafał Miłecki 	u32 fl_ctl;
1034dd4544f0SRafał Miłecki 	u16 bp_clk;
1035dd4544f0SRafał Miłecki 	u8 mdp;
1036dd4544f0SRafał Miłecki 
1037dd4544f0SRafał Miłecki 	cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
1038dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
103948e07fbeSHauke Mehrtens 			     BGMAC_CMDCFG_SR(bgmac->core->id.rev), true);
1040dd4544f0SRafał Miłecki 	udelay(2);
1041dd4544f0SRafał Miłecki 	cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
1042dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);
1043dd4544f0SRafał Miłecki 
1044dd4544f0SRafał Miłecki 	mode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
1045dd4544f0SRafał Miłecki 		BGMAC_DS_MM_SHIFT;
1046dd4544f0SRafał Miłecki 	if (ci->id != BCMA_CHIP_ID_BCM47162 || mode != 0)
1047dd4544f0SRafał Miłecki 		bgmac_set(bgmac, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
1048dd4544f0SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM47162 && mode == 2)
1049dd4544f0SRafał Miłecki 		bcma_chipco_chipctl_maskset(&bgmac->core->bus->drv_cc, 1, ~0,
1050dd4544f0SRafał Miłecki 					    BGMAC_CHIPCTL_1_RXC_DLL_BYPASS);
1051dd4544f0SRafał Miłecki 
1052dd4544f0SRafał Miłecki 	switch (ci->id) {
1053dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM5357:
1054dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM4749:
1055dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM53572:
1056dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM4716:
1057dd4544f0SRafał Miłecki 	case BCMA_CHIP_ID_BCM47162:
1058dd4544f0SRafał Miłecki 		fl_ctl = 0x03cb04cb;
1059dd4544f0SRafał Miłecki 		if (ci->id == BCMA_CHIP_ID_BCM5357 ||
1060dd4544f0SRafał Miłecki 		    ci->id == BCMA_CHIP_ID_BCM4749 ||
1061dd4544f0SRafał Miłecki 		    ci->id == BCMA_CHIP_ID_BCM53572)
1062dd4544f0SRafał Miłecki 			fl_ctl = 0x2300e1;
1063dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_FLOW_CTL_THRESH, fl_ctl);
1064dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_PAUSE_CTL, 0x27fff);
1065dd4544f0SRafał Miłecki 		break;
1066dd4544f0SRafał Miłecki 	}
1067dd4544f0SRafał Miłecki 
10686df4aff9SHauke Mehrtens 	if (ci->id != BCMA_CHIP_ID_BCM4707 &&
10696df4aff9SHauke Mehrtens 	    ci->id != BCMA_CHIP_ID_BCM53018) {
1070dd4544f0SRafał Miłecki 		rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
1071dd4544f0SRafał Miłecki 		rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
10726df4aff9SHauke Mehrtens 		bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) /
10736df4aff9SHauke Mehrtens 				1000000;
1074dd4544f0SRafał Miłecki 		mdp = (bp_clk * 128 / 1000) - 3;
1075dd4544f0SRafał Miłecki 		rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
1076dd4544f0SRafał Miłecki 		bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
1077dd4544f0SRafał Miłecki 	}
10786df4aff9SHauke Mehrtens }
1079dd4544f0SRafał Miłecki 
1080dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
1081dd4544f0SRafał Miłecki static void bgmac_chip_init(struct bgmac *bgmac, bool full_init)
1082dd4544f0SRafał Miłecki {
1083dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1084dd4544f0SRafał Miłecki 	int i;
1085dd4544f0SRafał Miłecki 
1086dd4544f0SRafał Miłecki 	/* 1 interrupt per received frame */
1087dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);
1088dd4544f0SRafał Miłecki 
1089dd4544f0SRafał Miłecki 	/* Enable 802.3x tx flow control (honor received PAUSE frames) */
1090dd4544f0SRafał Miłecki 	bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_RPI, 0, true);
1091dd4544f0SRafał Miłecki 
1092c6edfe10SHauke Mehrtens 	bgmac_set_rx_mode(bgmac->net_dev);
1093dd4544f0SRafał Miłecki 
10944e209001SHauke Mehrtens 	bgmac_write_mac_address(bgmac, bgmac->net_dev->dev_addr);
1095dd4544f0SRafał Miłecki 
1096dd4544f0SRafał Miłecki 	if (bgmac->loopback)
1097e9ba1039SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
1098dd4544f0SRafał Miłecki 	else
1099e9ba1039SRafał Miłecki 		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_ML, 0, false);
1100dd4544f0SRafał Miłecki 
1101dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN);
1102dd4544f0SRafał Miłecki 
1103dd4544f0SRafał Miłecki 	if (full_init) {
1104dd4544f0SRafał Miłecki 		bgmac_dma_init(bgmac);
1105dd4544f0SRafał Miłecki 		if (1) /* FIXME: is there any case we don't want IRQs? */
1106dd4544f0SRafał Miłecki 			bgmac_chip_intrs_on(bgmac);
1107dd4544f0SRafał Miłecki 	} else {
1108dd4544f0SRafał Miłecki 		for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
1109dd4544f0SRafał Miłecki 			ring = &bgmac->rx_ring[i];
1110dd4544f0SRafał Miłecki 			bgmac_dma_rx_enable(bgmac, ring);
1111dd4544f0SRafał Miłecki 		}
1112dd4544f0SRafał Miłecki 	}
1113dd4544f0SRafał Miłecki 
1114dd4544f0SRafał Miłecki 	bgmac_enable(bgmac);
1115dd4544f0SRafał Miłecki }
1116dd4544f0SRafał Miłecki 
1117dd4544f0SRafał Miłecki static irqreturn_t bgmac_interrupt(int irq, void *dev_id)
1118dd4544f0SRafał Miłecki {
1119dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(dev_id);
1120dd4544f0SRafał Miłecki 
1121dd4544f0SRafał Miłecki 	u32 int_status = bgmac_read(bgmac, BGMAC_INT_STATUS);
1122dd4544f0SRafał Miłecki 	int_status &= bgmac->int_mask;
1123dd4544f0SRafał Miłecki 
1124dd4544f0SRafał Miłecki 	if (!int_status)
1125dd4544f0SRafał Miłecki 		return IRQ_NONE;
1126dd4544f0SRafał Miłecki 
1127dd4544f0SRafał Miłecki 	/* Ack */
1128dd4544f0SRafał Miłecki 	bgmac_write(bgmac, BGMAC_INT_STATUS, int_status);
1129dd4544f0SRafał Miłecki 
1130dd4544f0SRafał Miłecki 	/* Disable new interrupts until handling existing ones */
1131dd4544f0SRafał Miłecki 	bgmac_chip_intrs_off(bgmac);
1132dd4544f0SRafał Miłecki 
1133dd4544f0SRafał Miłecki 	bgmac->int_status = int_status;
1134dd4544f0SRafał Miłecki 
1135dd4544f0SRafał Miłecki 	napi_schedule(&bgmac->napi);
1136dd4544f0SRafał Miłecki 
1137dd4544f0SRafał Miłecki 	return IRQ_HANDLED;
1138dd4544f0SRafał Miłecki }
1139dd4544f0SRafał Miłecki 
1140dd4544f0SRafał Miłecki static int bgmac_poll(struct napi_struct *napi, int weight)
1141dd4544f0SRafał Miłecki {
1142dd4544f0SRafał Miłecki 	struct bgmac *bgmac = container_of(napi, struct bgmac, napi);
1143dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1144dd4544f0SRafał Miłecki 	int handled = 0;
1145dd4544f0SRafał Miłecki 
1146dd4544f0SRafał Miłecki 	if (bgmac->int_status & BGMAC_IS_TX0) {
1147dd4544f0SRafał Miłecki 		ring = &bgmac->tx_ring[0];
1148dd4544f0SRafał Miłecki 		bgmac_dma_tx_free(bgmac, ring);
1149dd4544f0SRafał Miłecki 		bgmac->int_status &= ~BGMAC_IS_TX0;
1150dd4544f0SRafał Miłecki 	}
1151dd4544f0SRafał Miłecki 
1152dd4544f0SRafał Miłecki 	if (bgmac->int_status & BGMAC_IS_RX) {
1153dd4544f0SRafał Miłecki 		ring = &bgmac->rx_ring[0];
1154dd4544f0SRafał Miłecki 		handled += bgmac_dma_rx_read(bgmac, ring, weight);
1155dd4544f0SRafał Miłecki 		bgmac->int_status &= ~BGMAC_IS_RX;
1156dd4544f0SRafał Miłecki 	}
1157dd4544f0SRafał Miłecki 
1158dd4544f0SRafał Miłecki 	if (bgmac->int_status) {
1159dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", bgmac->int_status);
1160dd4544f0SRafał Miłecki 		bgmac->int_status = 0;
1161dd4544f0SRafał Miłecki 	}
1162dd4544f0SRafał Miłecki 
116343f159c6SHauke Mehrtens 	if (handled < weight) {
1164dd4544f0SRafał Miłecki 		napi_complete(napi);
1165dd4544f0SRafał Miłecki 		bgmac_chip_intrs_on(bgmac);
116643f159c6SHauke Mehrtens 	}
1167dd4544f0SRafał Miłecki 
1168dd4544f0SRafał Miłecki 	return handled;
1169dd4544f0SRafał Miłecki }
1170dd4544f0SRafał Miłecki 
1171dd4544f0SRafał Miłecki /**************************************************
1172dd4544f0SRafał Miłecki  * net_device_ops
1173dd4544f0SRafał Miłecki  **************************************************/
1174dd4544f0SRafał Miłecki 
1175dd4544f0SRafał Miłecki static int bgmac_open(struct net_device *net_dev)
1176dd4544f0SRafał Miłecki {
1177dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1178dd4544f0SRafał Miłecki 	int err = 0;
1179dd4544f0SRafał Miłecki 
1180dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1181dd4544f0SRafał Miłecki 	/* Specs say about reclaiming rings here, but we do that in DMA init */
1182dd4544f0SRafał Miłecki 	bgmac_chip_init(bgmac, true);
1183dd4544f0SRafał Miłecki 
1184dd4544f0SRafał Miłecki 	err = request_irq(bgmac->core->irq, bgmac_interrupt, IRQF_SHARED,
1185dd4544f0SRafał Miłecki 			  KBUILD_MODNAME, net_dev);
1186dd4544f0SRafał Miłecki 	if (err < 0) {
1187dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "IRQ request error: %d!\n", err);
1188dd4544f0SRafał Miłecki 		goto err_out;
1189dd4544f0SRafał Miłecki 	}
1190dd4544f0SRafał Miłecki 	napi_enable(&bgmac->napi);
1191dd4544f0SRafał Miłecki 
11924e34da4dSRafał Miłecki 	phy_start(bgmac->phy_dev);
11934e34da4dSRafał Miłecki 
1194dd4544f0SRafał Miłecki 	netif_carrier_on(net_dev);
1195dd4544f0SRafał Miłecki 
1196dd4544f0SRafał Miłecki err_out:
1197dd4544f0SRafał Miłecki 	return err;
1198dd4544f0SRafał Miłecki }
1199dd4544f0SRafał Miłecki 
1200dd4544f0SRafał Miłecki static int bgmac_stop(struct net_device *net_dev)
1201dd4544f0SRafał Miłecki {
1202dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1203dd4544f0SRafał Miłecki 
1204dd4544f0SRafał Miłecki 	netif_carrier_off(net_dev);
1205dd4544f0SRafał Miłecki 
12064e34da4dSRafał Miłecki 	phy_stop(bgmac->phy_dev);
12074e34da4dSRafał Miłecki 
1208dd4544f0SRafał Miłecki 	napi_disable(&bgmac->napi);
1209dd4544f0SRafał Miłecki 	bgmac_chip_intrs_off(bgmac);
1210dd4544f0SRafał Miłecki 	free_irq(bgmac->core->irq, net_dev);
1211dd4544f0SRafał Miłecki 
1212dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1213dd4544f0SRafał Miłecki 
1214dd4544f0SRafał Miłecki 	return 0;
1215dd4544f0SRafał Miłecki }
1216dd4544f0SRafał Miłecki 
1217dd4544f0SRafał Miłecki static netdev_tx_t bgmac_start_xmit(struct sk_buff *skb,
1218dd4544f0SRafał Miłecki 				    struct net_device *net_dev)
1219dd4544f0SRafał Miłecki {
1220dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1221dd4544f0SRafał Miłecki 	struct bgmac_dma_ring *ring;
1222dd4544f0SRafał Miłecki 
1223dd4544f0SRafał Miłecki 	/* No QOS support yet */
1224dd4544f0SRafał Miłecki 	ring = &bgmac->tx_ring[0];
1225dd4544f0SRafał Miłecki 	return bgmac_dma_tx_add(bgmac, ring, skb);
1226dd4544f0SRafał Miłecki }
1227dd4544f0SRafał Miłecki 
12284e209001SHauke Mehrtens static int bgmac_set_mac_address(struct net_device *net_dev, void *addr)
12294e209001SHauke Mehrtens {
12304e209001SHauke Mehrtens 	struct bgmac *bgmac = netdev_priv(net_dev);
12314e209001SHauke Mehrtens 	int ret;
12324e209001SHauke Mehrtens 
12334e209001SHauke Mehrtens 	ret = eth_prepare_mac_addr_change(net_dev, addr);
12344e209001SHauke Mehrtens 	if (ret < 0)
12354e209001SHauke Mehrtens 		return ret;
12364e209001SHauke Mehrtens 	bgmac_write_mac_address(bgmac, (u8 *)addr);
12374e209001SHauke Mehrtens 	eth_commit_mac_addr_change(net_dev, addr);
12384e209001SHauke Mehrtens 	return 0;
12394e209001SHauke Mehrtens }
12404e209001SHauke Mehrtens 
1241dd4544f0SRafał Miłecki static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
1242dd4544f0SRafał Miłecki {
1243dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1244dd4544f0SRafał Miłecki 
1245dd4544f0SRafał Miłecki 	if (!netif_running(net_dev))
124669c58852SHauke Mehrtens 		return -EINVAL;
124769c58852SHauke Mehrtens 
124869c58852SHauke Mehrtens 	return phy_mii_ioctl(bgmac->phy_dev, ifr, cmd);
1249dd4544f0SRafał Miłecki }
1250dd4544f0SRafał Miłecki 
1251dd4544f0SRafał Miłecki static const struct net_device_ops bgmac_netdev_ops = {
1252dd4544f0SRafał Miłecki 	.ndo_open		= bgmac_open,
1253dd4544f0SRafał Miłecki 	.ndo_stop		= bgmac_stop,
1254dd4544f0SRafał Miłecki 	.ndo_start_xmit		= bgmac_start_xmit,
1255c6edfe10SHauke Mehrtens 	.ndo_set_rx_mode	= bgmac_set_rx_mode,
12564e209001SHauke Mehrtens 	.ndo_set_mac_address	= bgmac_set_mac_address,
1257522c5907SHauke Mehrtens 	.ndo_validate_addr	= eth_validate_addr,
1258dd4544f0SRafał Miłecki 	.ndo_do_ioctl           = bgmac_ioctl,
1259dd4544f0SRafał Miłecki };
1260dd4544f0SRafał Miłecki 
1261dd4544f0SRafał Miłecki /**************************************************
1262dd4544f0SRafał Miłecki  * ethtool_ops
1263dd4544f0SRafał Miłecki  **************************************************/
1264dd4544f0SRafał Miłecki 
1265dd4544f0SRafał Miłecki static int bgmac_get_settings(struct net_device *net_dev,
1266dd4544f0SRafał Miłecki 			      struct ethtool_cmd *cmd)
1267dd4544f0SRafał Miłecki {
1268dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1269dd4544f0SRafał Miłecki 
12705824d2d1SRafał Miłecki 	return phy_ethtool_gset(bgmac->phy_dev, cmd);
1271dd4544f0SRafał Miłecki }
1272dd4544f0SRafał Miłecki 
1273dd4544f0SRafał Miłecki static int bgmac_set_settings(struct net_device *net_dev,
1274dd4544f0SRafał Miłecki 			      struct ethtool_cmd *cmd)
1275dd4544f0SRafał Miłecki {
1276dd4544f0SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
1277dd4544f0SRafał Miłecki 
12785824d2d1SRafał Miłecki 	return phy_ethtool_sset(bgmac->phy_dev, cmd);
1279dd4544f0SRafał Miłecki }
1280dd4544f0SRafał Miłecki 
1281dd4544f0SRafał Miłecki static void bgmac_get_drvinfo(struct net_device *net_dev,
1282dd4544f0SRafał Miłecki 			      struct ethtool_drvinfo *info)
1283dd4544f0SRafał Miłecki {
1284dd4544f0SRafał Miłecki 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
1285dd4544f0SRafał Miłecki 	strlcpy(info->bus_info, "BCMA", sizeof(info->bus_info));
1286dd4544f0SRafał Miłecki }
1287dd4544f0SRafał Miłecki 
1288dd4544f0SRafał Miłecki static const struct ethtool_ops bgmac_ethtool_ops = {
1289dd4544f0SRafał Miłecki 	.get_settings		= bgmac_get_settings,
12905824d2d1SRafał Miłecki 	.set_settings		= bgmac_set_settings,
1291dd4544f0SRafał Miłecki 	.get_drvinfo		= bgmac_get_drvinfo,
1292dd4544f0SRafał Miłecki };
1293dd4544f0SRafał Miłecki 
1294dd4544f0SRafał Miłecki /**************************************************
129511e5e76eSRafał Miłecki  * MII
129611e5e76eSRafał Miłecki  **************************************************/
129711e5e76eSRafał Miłecki 
129811e5e76eSRafał Miłecki static int bgmac_mii_read(struct mii_bus *bus, int mii_id, int regnum)
129911e5e76eSRafał Miłecki {
130011e5e76eSRafał Miłecki 	return bgmac_phy_read(bus->priv, mii_id, regnum);
130111e5e76eSRafał Miłecki }
130211e5e76eSRafał Miłecki 
130311e5e76eSRafał Miłecki static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum,
130411e5e76eSRafał Miłecki 			   u16 value)
130511e5e76eSRafał Miłecki {
130611e5e76eSRafał Miłecki 	return bgmac_phy_write(bus->priv, mii_id, regnum, value);
130711e5e76eSRafał Miłecki }
130811e5e76eSRafał Miłecki 
13095824d2d1SRafał Miłecki static void bgmac_adjust_link(struct net_device *net_dev)
13105824d2d1SRafał Miłecki {
13115824d2d1SRafał Miłecki 	struct bgmac *bgmac = netdev_priv(net_dev);
13125824d2d1SRafał Miłecki 	struct phy_device *phy_dev = bgmac->phy_dev;
13135824d2d1SRafał Miłecki 	bool update = false;
13145824d2d1SRafał Miłecki 
13155824d2d1SRafał Miłecki 	if (phy_dev->link) {
13165824d2d1SRafał Miłecki 		if (phy_dev->speed != bgmac->mac_speed) {
13175824d2d1SRafał Miłecki 			bgmac->mac_speed = phy_dev->speed;
13185824d2d1SRafał Miłecki 			update = true;
13195824d2d1SRafał Miłecki 		}
13205824d2d1SRafał Miłecki 
13215824d2d1SRafał Miłecki 		if (phy_dev->duplex != bgmac->mac_duplex) {
13225824d2d1SRafał Miłecki 			bgmac->mac_duplex = phy_dev->duplex;
13235824d2d1SRafał Miłecki 			update = true;
13245824d2d1SRafał Miłecki 		}
13255824d2d1SRafał Miłecki 	}
13265824d2d1SRafał Miłecki 
13275824d2d1SRafał Miłecki 	if (update) {
13285824d2d1SRafał Miłecki 		bgmac_mac_speed(bgmac);
13295824d2d1SRafał Miłecki 		phy_print_status(phy_dev);
13305824d2d1SRafał Miłecki 	}
13315824d2d1SRafał Miłecki }
13325824d2d1SRafał Miłecki 
133311e5e76eSRafał Miłecki static int bgmac_mii_register(struct bgmac *bgmac)
133411e5e76eSRafał Miłecki {
133511e5e76eSRafał Miłecki 	struct mii_bus *mii_bus;
13365824d2d1SRafał Miłecki 	struct phy_device *phy_dev;
13375824d2d1SRafał Miłecki 	char bus_id[MII_BUS_ID_SIZE + 3];
133811e5e76eSRafał Miłecki 	int i, err = 0;
133911e5e76eSRafał Miłecki 
134011e5e76eSRafał Miłecki 	mii_bus = mdiobus_alloc();
134111e5e76eSRafał Miłecki 	if (!mii_bus)
134211e5e76eSRafał Miłecki 		return -ENOMEM;
134311e5e76eSRafał Miłecki 
134411e5e76eSRafał Miłecki 	mii_bus->name = "bgmac mii bus";
134511e5e76eSRafał Miłecki 	sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
134611e5e76eSRafał Miłecki 		bgmac->core->core_unit);
134711e5e76eSRafał Miłecki 	mii_bus->priv = bgmac;
134811e5e76eSRafał Miłecki 	mii_bus->read = bgmac_mii_read;
134911e5e76eSRafał Miłecki 	mii_bus->write = bgmac_mii_write;
135011e5e76eSRafał Miłecki 	mii_bus->parent = &bgmac->core->dev;
135111e5e76eSRafał Miłecki 	mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
135211e5e76eSRafał Miłecki 
135311e5e76eSRafał Miłecki 	mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
135411e5e76eSRafał Miłecki 	if (!mii_bus->irq) {
135511e5e76eSRafał Miłecki 		err = -ENOMEM;
135611e5e76eSRafał Miłecki 		goto err_free_bus;
135711e5e76eSRafał Miłecki 	}
135811e5e76eSRafał Miłecki 	for (i = 0; i < PHY_MAX_ADDR; i++)
135911e5e76eSRafał Miłecki 		mii_bus->irq[i] = PHY_POLL;
136011e5e76eSRafał Miłecki 
136111e5e76eSRafał Miłecki 	err = mdiobus_register(mii_bus);
136211e5e76eSRafał Miłecki 	if (err) {
136311e5e76eSRafał Miłecki 		bgmac_err(bgmac, "Registration of mii bus failed\n");
136411e5e76eSRafał Miłecki 		goto err_free_irq;
136511e5e76eSRafał Miłecki 	}
136611e5e76eSRafał Miłecki 
136711e5e76eSRafał Miłecki 	bgmac->mii_bus = mii_bus;
136811e5e76eSRafał Miłecki 
13695824d2d1SRafał Miłecki 	/* Connect to the PHY */
13705824d2d1SRafał Miłecki 	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
13715824d2d1SRafał Miłecki 		 bgmac->phyaddr);
13725824d2d1SRafał Miłecki 	phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
13735824d2d1SRafał Miłecki 			      PHY_INTERFACE_MODE_MII);
13745824d2d1SRafał Miłecki 	if (IS_ERR(phy_dev)) {
13755824d2d1SRafał Miłecki 		bgmac_err(bgmac, "PHY connecton failed\n");
13765824d2d1SRafał Miłecki 		err = PTR_ERR(phy_dev);
13775824d2d1SRafał Miłecki 		goto err_unregister_bus;
13785824d2d1SRafał Miłecki 	}
13795824d2d1SRafał Miłecki 	bgmac->phy_dev = phy_dev;
13805824d2d1SRafał Miłecki 
138111e5e76eSRafał Miłecki 	return err;
138211e5e76eSRafał Miłecki 
13835824d2d1SRafał Miłecki err_unregister_bus:
13845824d2d1SRafał Miłecki 	mdiobus_unregister(mii_bus);
138511e5e76eSRafał Miłecki err_free_irq:
138611e5e76eSRafał Miłecki 	kfree(mii_bus->irq);
138711e5e76eSRafał Miłecki err_free_bus:
138811e5e76eSRafał Miłecki 	mdiobus_free(mii_bus);
138911e5e76eSRafał Miłecki 	return err;
139011e5e76eSRafał Miłecki }
139111e5e76eSRafał Miłecki 
139211e5e76eSRafał Miłecki static void bgmac_mii_unregister(struct bgmac *bgmac)
139311e5e76eSRafał Miłecki {
139411e5e76eSRafał Miłecki 	struct mii_bus *mii_bus = bgmac->mii_bus;
139511e5e76eSRafał Miłecki 
139611e5e76eSRafał Miłecki 	mdiobus_unregister(mii_bus);
139711e5e76eSRafał Miłecki 	kfree(mii_bus->irq);
139811e5e76eSRafał Miłecki 	mdiobus_free(mii_bus);
139911e5e76eSRafał Miłecki }
140011e5e76eSRafał Miłecki 
140111e5e76eSRafał Miłecki /**************************************************
1402dd4544f0SRafał Miłecki  * BCMA bus ops
1403dd4544f0SRafał Miłecki  **************************************************/
1404dd4544f0SRafał Miłecki 
1405dd4544f0SRafał Miłecki /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
1406dd4544f0SRafał Miłecki static int bgmac_probe(struct bcma_device *core)
1407dd4544f0SRafał Miłecki {
140821697336SRafał Miłecki 	struct bcma_chipinfo *ci = &core->bus->chipinfo;
1409dd4544f0SRafał Miłecki 	struct net_device *net_dev;
1410dd4544f0SRafał Miłecki 	struct bgmac *bgmac;
1411dd4544f0SRafał Miłecki 	struct ssb_sprom *sprom = &core->bus->sprom;
1412dd4544f0SRafał Miłecki 	u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac;
1413dd4544f0SRafał Miłecki 	int err;
1414dd4544f0SRafał Miłecki 
1415dd4544f0SRafał Miłecki 	/* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */
1416dd4544f0SRafał Miłecki 	if (core->core_unit > 1) {
1417dd4544f0SRafał Miłecki 		pr_err("Unsupported core_unit %d\n", core->core_unit);
1418dd4544f0SRafał Miłecki 		return -ENOTSUPP;
1419dd4544f0SRafał Miłecki 	}
1420dd4544f0SRafał Miłecki 
1421d166f218SRafał Miłecki 	if (!is_valid_ether_addr(mac)) {
1422d166f218SRafał Miłecki 		dev_err(&core->dev, "Invalid MAC addr: %pM\n", mac);
1423d166f218SRafał Miłecki 		eth_random_addr(mac);
1424d166f218SRafał Miłecki 		dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
1425d166f218SRafał Miłecki 	}
1426d166f218SRafał Miłecki 
1427dd4544f0SRafał Miłecki 	/* Allocation and references */
1428dd4544f0SRafał Miłecki 	net_dev = alloc_etherdev(sizeof(*bgmac));
1429dd4544f0SRafał Miłecki 	if (!net_dev)
1430dd4544f0SRafał Miłecki 		return -ENOMEM;
1431dd4544f0SRafał Miłecki 	net_dev->netdev_ops = &bgmac_netdev_ops;
1432dd4544f0SRafał Miłecki 	net_dev->irq = core->irq;
14337ad24ea4SWilfried Klaebe 	net_dev->ethtool_ops = &bgmac_ethtool_ops;
1434dd4544f0SRafał Miłecki 	bgmac = netdev_priv(net_dev);
1435dd4544f0SRafał Miłecki 	bgmac->net_dev = net_dev;
1436dd4544f0SRafał Miłecki 	bgmac->core = core;
1437dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, bgmac);
1438dd4544f0SRafał Miłecki 
1439dd4544f0SRafał Miłecki 	/* Defaults */
1440dd4544f0SRafał Miłecki 	memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
1441dd4544f0SRafał Miłecki 
1442dd4544f0SRafał Miłecki 	/* On BCM4706 we need common core to access PHY */
1443dd4544f0SRafał Miłecki 	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
1444dd4544f0SRafał Miłecki 	    !core->bus->drv_gmac_cmn.core) {
1445dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "GMAC CMN core not found (required for BCM4706)\n");
1446dd4544f0SRafał Miłecki 		err = -ENODEV;
1447dd4544f0SRafał Miłecki 		goto err_netdev_free;
1448dd4544f0SRafał Miłecki 	}
1449dd4544f0SRafał Miłecki 	bgmac->cmn = core->bus->drv_gmac_cmn.core;
1450dd4544f0SRafał Miłecki 
1451dd4544f0SRafał Miłecki 	bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr :
1452dd4544f0SRafał Miłecki 			 sprom->et0phyaddr;
1453dd4544f0SRafał Miłecki 	bgmac->phyaddr &= BGMAC_PHY_MASK;
1454dd4544f0SRafał Miłecki 	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
1455dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "No PHY found\n");
1456dd4544f0SRafał Miłecki 		err = -ENODEV;
1457dd4544f0SRafał Miłecki 		goto err_netdev_free;
1458dd4544f0SRafał Miłecki 	}
1459dd4544f0SRafał Miłecki 	bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr,
1460dd4544f0SRafał Miłecki 		   bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
1461dd4544f0SRafał Miłecki 
1462dd4544f0SRafał Miłecki 	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
1463dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "PCI setup not implemented\n");
1464dd4544f0SRafał Miłecki 		err = -ENOTSUPP;
1465dd4544f0SRafał Miłecki 		goto err_netdev_free;
1466dd4544f0SRafał Miłecki 	}
1467dd4544f0SRafał Miłecki 
1468dd4544f0SRafał Miłecki 	bgmac_chip_reset(bgmac);
1469dd4544f0SRafał Miłecki 
1470622a521fSHauke Mehrtens 	/* For Northstar, we have to take all GMAC core out of reset */
147121697336SRafał Miłecki 	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
147221697336SRafał Miłecki 	    ci->id == BCMA_CHIP_ID_BCM53018) {
1473622a521fSHauke Mehrtens 		struct bcma_device *ns_core;
1474622a521fSHauke Mehrtens 		int ns_gmac;
1475622a521fSHauke Mehrtens 
1476622a521fSHauke Mehrtens 		/* Northstar has 4 GMAC cores */
1477622a521fSHauke Mehrtens 		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
14780e595934SHauke Mehrtens 			/* As Northstar requirement, we have to reset all GMACs
1479622a521fSHauke Mehrtens 			 * before accessing one. bgmac_chip_reset() call
1480622a521fSHauke Mehrtens 			 * bcma_core_enable() for this core. Then the other
14810e595934SHauke Mehrtens 			 * three GMACs didn't reset.  We do it here.
1482622a521fSHauke Mehrtens 			 */
1483622a521fSHauke Mehrtens 			ns_core = bcma_find_core_unit(core->bus,
1484622a521fSHauke Mehrtens 						      BCMA_CORE_MAC_GBIT,
1485622a521fSHauke Mehrtens 						      ns_gmac);
1486622a521fSHauke Mehrtens 			if (ns_core && !bcma_core_is_enabled(ns_core))
1487622a521fSHauke Mehrtens 				bcma_core_enable(ns_core, 0);
1488622a521fSHauke Mehrtens 		}
1489622a521fSHauke Mehrtens 	}
1490622a521fSHauke Mehrtens 
1491dd4544f0SRafał Miłecki 	err = bgmac_dma_alloc(bgmac);
1492dd4544f0SRafał Miłecki 	if (err) {
1493dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Unable to alloc memory for DMA\n");
1494dd4544f0SRafał Miłecki 		goto err_netdev_free;
1495dd4544f0SRafał Miłecki 	}
1496dd4544f0SRafał Miłecki 
1497dd4544f0SRafał Miłecki 	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
1498edb15d83SRalf Baechle 	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
1499dd4544f0SRafał Miłecki 		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;
1500dd4544f0SRafał Miłecki 
1501dd4544f0SRafał Miłecki 	/* TODO: reset the external phy. Specs are needed */
1502dd4544f0SRafał Miłecki 	bgmac_phy_reset(bgmac);
1503dd4544f0SRafał Miłecki 
1504dd4544f0SRafał Miłecki 	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
1505dd4544f0SRafał Miłecki 			       BGMAC_BFL_ENETROBO);
1506dd4544f0SRafał Miłecki 	if (bgmac->has_robosw)
1507dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Support for Roboswitch not implemented\n");
1508dd4544f0SRafał Miłecki 
1509dd4544f0SRafał Miłecki 	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
1510dd4544f0SRafał Miłecki 		bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
1511dd4544f0SRafał Miłecki 
15126216642fSHauke Mehrtens 	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
15136216642fSHauke Mehrtens 
151411e5e76eSRafał Miłecki 	err = bgmac_mii_register(bgmac);
151511e5e76eSRafał Miłecki 	if (err) {
151611e5e76eSRafał Miłecki 		bgmac_err(bgmac, "Cannot register MDIO\n");
151711e5e76eSRafał Miłecki 		goto err_dma_free;
151811e5e76eSRafał Miłecki 	}
151911e5e76eSRafał Miłecki 
1520dd4544f0SRafał Miłecki 	err = register_netdev(bgmac->net_dev);
1521dd4544f0SRafał Miłecki 	if (err) {
1522dd4544f0SRafał Miłecki 		bgmac_err(bgmac, "Cannot register net device\n");
152311e5e76eSRafał Miłecki 		goto err_mii_unregister;
1524dd4544f0SRafał Miłecki 	}
1525dd4544f0SRafał Miłecki 
1526dd4544f0SRafał Miłecki 	netif_carrier_off(net_dev);
1527dd4544f0SRafał Miłecki 
1528dd4544f0SRafał Miłecki 	return 0;
1529dd4544f0SRafał Miłecki 
153011e5e76eSRafał Miłecki err_mii_unregister:
153111e5e76eSRafał Miłecki 	bgmac_mii_unregister(bgmac);
1532dd4544f0SRafał Miłecki err_dma_free:
1533dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
1534dd4544f0SRafał Miłecki 
1535dd4544f0SRafał Miłecki err_netdev_free:
1536dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, NULL);
1537dd4544f0SRafał Miłecki 	free_netdev(net_dev);
1538dd4544f0SRafał Miłecki 
1539dd4544f0SRafał Miłecki 	return err;
1540dd4544f0SRafał Miłecki }
1541dd4544f0SRafał Miłecki 
1542dd4544f0SRafał Miłecki static void bgmac_remove(struct bcma_device *core)
1543dd4544f0SRafał Miłecki {
1544dd4544f0SRafał Miłecki 	struct bgmac *bgmac = bcma_get_drvdata(core);
1545dd4544f0SRafał Miłecki 
1546dd4544f0SRafał Miłecki 	unregister_netdev(bgmac->net_dev);
154711e5e76eSRafał Miłecki 	bgmac_mii_unregister(bgmac);
15486216642fSHauke Mehrtens 	netif_napi_del(&bgmac->napi);
1549dd4544f0SRafał Miłecki 	bgmac_dma_free(bgmac);
1550dd4544f0SRafał Miłecki 	bcma_set_drvdata(core, NULL);
1551dd4544f0SRafał Miłecki 	free_netdev(bgmac->net_dev);
1552dd4544f0SRafał Miłecki }
1553dd4544f0SRafał Miłecki 
1554dd4544f0SRafał Miłecki static struct bcma_driver bgmac_bcma_driver = {
1555dd4544f0SRafał Miłecki 	.name		= KBUILD_MODNAME,
1556dd4544f0SRafał Miłecki 	.id_table	= bgmac_bcma_tbl,
1557dd4544f0SRafał Miłecki 	.probe		= bgmac_probe,
1558dd4544f0SRafał Miłecki 	.remove		= bgmac_remove,
1559dd4544f0SRafał Miłecki };
1560dd4544f0SRafał Miłecki 
1561dd4544f0SRafał Miłecki static int __init bgmac_init(void)
1562dd4544f0SRafał Miłecki {
1563dd4544f0SRafał Miłecki 	int err;
1564dd4544f0SRafał Miłecki 
1565dd4544f0SRafał Miłecki 	err = bcma_driver_register(&bgmac_bcma_driver);
1566dd4544f0SRafał Miłecki 	if (err)
1567dd4544f0SRafał Miłecki 		return err;
1568dd4544f0SRafał Miłecki 	pr_info("Broadcom 47xx GBit MAC driver loaded\n");
1569dd4544f0SRafał Miłecki 
1570dd4544f0SRafał Miłecki 	return 0;
1571dd4544f0SRafał Miłecki }
1572dd4544f0SRafał Miłecki 
1573dd4544f0SRafał Miłecki static void __exit bgmac_exit(void)
1574dd4544f0SRafał Miłecki {
1575dd4544f0SRafał Miłecki 	bcma_driver_unregister(&bgmac_bcma_driver);
1576dd4544f0SRafał Miłecki }
1577dd4544f0SRafał Miłecki 
1578dd4544f0SRafał Miłecki module_init(bgmac_init)
1579dd4544f0SRafał Miłecki module_exit(bgmac_exit)
1580dd4544f0SRafał Miłecki 
1581dd4544f0SRafał Miłecki MODULE_AUTHOR("Rafał Miłecki");
1582dd4544f0SRafał Miłecki MODULE_LICENSE("GPL");
1583