فهرست منبع

kernel: bgmac: make it send and receive some packages on BCM4708

This adds some more code for bgmac core rev 4 and it now restarts all
cores when initializing the first one on BCM4708. I am just able to
send under 100 packages and then DMA TX does not work any more.

Signed-off-by: Hauke Mehrtens <[email protected]>

SVN-Revision: 38714
Hauke Mehrtens 12 سال پیش
والد
کامیت
7444a626e2

+ 69 - 0
target/linux/generic/patches-3.10/026-bcma-export-bcma_find_core_unit.patch

@@ -0,0 +1,69 @@
+From 0fc9d696e4855f1e03910c431499d68e75904929 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <[email protected]>
+Date: Sun, 10 Nov 2013 20:43:46 +0100
+Subject: [PATCH] bcma: export bcma_find_core_unit()
+
+---
+ drivers/bcma/bcma_private.h |    2 --
+ drivers/bcma/main.c         |   13 +------------
+ include/linux/bcma/bcma.h   |    9 ++++++++-
+ 3 files changed, 9 insertions(+), 15 deletions(-)
+
+--- a/drivers/bcma/bcma_private.h
++++ b/drivers/bcma/bcma_private.h
+@@ -33,8 +33,6 @@ int __init bcma_bus_early_register(struc
+ int bcma_bus_suspend(struct bcma_bus *bus);
+ int bcma_bus_resume(struct bcma_bus *bus);
+ #endif
+-struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+-					u8 unit);
+ 
+ /* scan.c */
+ int bcma_bus_scan(struct bcma_bus *bus);
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -69,18 +69,6 @@ static u16 bcma_cc_core_id(struct bcma_b
+ 	return BCMA_CORE_CHIPCOMMON;
+ }
+ 
+-struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+-{
+-	struct bcma_device *core;
+-
+-	list_for_each_entry(core, &bus->cores, list) {
+-		if (core->id.id == coreid)
+-			return core;
+-	}
+-	return NULL;
+-}
+-EXPORT_SYMBOL_GPL(bcma_find_core);
+-
+ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+ 					u8 unit)
+ {
+@@ -92,6 +80,7 @@ struct bcma_device *bcma_find_core_unit(
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(bcma_find_core_unit);
+ 
+ bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
+ 		     int timeout)
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -418,7 +418,14 @@ static inline void bcma_maskset16(struct
+ 	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
+ }
+ 
+-extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
++extern struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
++					       u8 unit);
++static inline struct bcma_device *bcma_find_core(struct bcma_bus *bus,
++						 u16 coreid)
++{
++	return bcma_find_core_unit(bus, coreid, 0);
++}
++
+ extern bool bcma_core_is_enabled(struct bcma_device *core);
+ extern void bcma_core_disable(struct bcma_device *core, u32 flags);
+ extern int bcma_core_enable(struct bcma_device *core, u32 flags);

+ 26 - 0
target/linux/generic/patches-3.10/772-bgmac-add-supprot-for-BCM4707.patch

@@ -97,6 +97,32 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  }
  
  /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
+@@ -1488,6 +1512,25 @@ static int bgmac_probe(struct bcma_devic
+ 		goto err_netdev_free;
+ 	}
+ 
++	/* Northstar, take all GMAC cores out of reset */
++	if (core->id.id == BCMA_CHIP_ID_BCM4707 ||
++	    core->id.id == BCMA_CHIP_ID_BCM53018) {
++		struct bcma_device *ns_core;
++		int ns_gmac;
++
++		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
++			/* As northstar requirement, we have to reset all GAMCs before
++			 * accessing them. et_probe() call pci_enable_device() for etx
++			 * and do si_core_reset for GAMCx only.	 Then the other three
++			 * GAMCs didn't reset.  We do it here.
++			 */
++			ns_core = bcma_find_core_unit(core->bus, BCMA_CORE_MAC_GBIT, ns_gmac);
++			if (!bcma_core_is_enabled(ns_core)) {
++				bcma_core_enable(ns_core, 0);
++			}
++		}
++	}
++
+ 	bgmac_chip_reset(bgmac);
+ 
+ 	err = bgmac_dma_alloc(bgmac);
 --- a/drivers/net/ethernet/broadcom/bgmac.h
 +++ b/drivers/net/ethernet/broadcom/bgmac.h
 @@ -185,6 +185,7 @@

+ 2 - 2
target/linux/generic/patches-3.10/773-bgmac-add-srab-switch.patch

@@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  /**************************************************
   * BCMA bus ops
   **************************************************/
-@@ -1542,6 +1554,16 @@ static int bgmac_probe(struct bcma_devic
+@@ -1561,6 +1573,16 @@ static int bgmac_probe(struct bcma_devic
  		goto err_dma_free;
  	}
  
@@ -47,7 +47,7 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  	err = register_netdev(bgmac->net_dev);
  	if (err) {
  		bgmac_err(bgmac, "Cannot register net device\n");
-@@ -1571,6 +1593,10 @@ static void bgmac_remove(struct bcma_dev
+@@ -1590,6 +1612,10 @@ static void bgmac_remove(struct bcma_dev
  {
  	struct bgmac *bgmac = bcma_get_drvdata(core);
  

+ 163 - 0
target/linux/generic/patches-3.10/774-bgmac-add-some-workaround-for-rev-4.patch

@@ -0,0 +1,163 @@
+From ec12b94d22fa8715561bdffe6da0781dac08423e Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <[email protected]>
+Date: Sun, 10 Nov 2013 21:23:57 +0100
+Subject: [PATCH] bgmac: add some workaround for rev 4
+
+---
+ drivers/net/ethernet/broadcom/bgmac.c |    8 ++++----
+ drivers/net/ethernet/broadcom/bgmac.h |    4 +++-
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -97,6 +97,16 @@ static void bgmac_dma_tx_enable(struct b
+ 	u32 ctl;
+ 
+ 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
++	if (bgmac->core->id.rev == 4) {
++		ctl &= ~BGMAC_DMA_TX_BL_MASK;
++		ctl |= BGMAC_DMA_TX_BL_128 << BGMAC_DMA_TX_BL_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_MR_MASK;
++		ctl |= BGMAC_DMA_TX_MR_2 << BGMAC_DMA_TX_MR_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_PC_MASK;
++		ctl |= BGMAC_DMA_TX_PC_16 << BGMAC_DMA_TX_PC_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_PT_MASK;
++		ctl |= BGMAC_DMA_TX_PT_8 << BGMAC_DMA_TX_PT_SHIFT;
++	}
+ 	ctl |= BGMAC_DMA_TX_ENABLE;
+ 	ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
+ 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
+@@ -246,6 +256,17 @@ static void bgmac_dma_rx_enable(struct b
+ 	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
+ 	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
+ 	ctl |= BGMAC_RX_FRAME_OFFSET << BGMAC_DMA_RX_FRAME_OFFSET_SHIFT;
++
++	if (bgmac->core->id.rev == 4) {
++		ctl &= ~BGMAC_DMA_RX_BL_MASK;
++		ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;
++
++		ctl &= ~BGMAC_DMA_RX_PC_MASK;
++		ctl |= BGMAC_DMA_RX_PC_8 << BGMAC_DMA_RX_PC_SHIFT;
++
++		ctl &= ~BGMAC_DMA_RX_PT_MASK;
++		ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
++	}
+ 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, ctl);
+ }
+ 
+@@ -812,13 +833,13 @@ static void bgmac_cmdcfg_maskset(struct
+ 	u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
+ 	u32 new_val = (cmdcfg & mask) | set;
+ 
+-	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR);
++	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR(bgmac->core->id.rev));
+ 	udelay(2);
+ 
+ 	if (new_val != cmdcfg || force)
+ 		bgmac_write(bgmac, BGMAC_CMDCFG, new_val);
+ 
+-	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR);
++	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR(bgmac->core->id.rev));
+ 	udelay(2);
+ }
+ 
+@@ -1029,7 +1050,7 @@ static void bgmac_chip_reset(struct bgma
+ 			     BGMAC_CMDCFG_PROM |
+ 			     BGMAC_CMDCFG_NLC |
+ 			     BGMAC_CMDCFG_CFE |
+-			     BGMAC_CMDCFG_SR,
++			     BGMAC_CMDCFG_SR(core->id.rev),
+ 			     false);
+ 
+ 	bgmac_clear_mib(bgmac);
+@@ -1070,7 +1091,7 @@ static void bgmac_enable(struct bgmac *b
+ 
+ 	cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
+ 	bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
+-			     BGMAC_CMDCFG_SR, true);
++			     BGMAC_CMDCFG_SR(bgmac->core->id.rev), true);
+ 	udelay(2);
+ 	cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
+ 	bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);
+--- a/drivers/net/ethernet/broadcom/bgmac.h
++++ b/drivers/net/ethernet/broadcom/bgmac.h
+@@ -194,7 +194,9 @@
+ #define  BGMAC_CMDCFG_TAI			0x00000200
+ #define  BGMAC_CMDCFG_HD			0x00000400	/* Set if in half duplex mode */
+ #define  BGMAC_CMDCFG_HD_SHIFT			10
+-#define  BGMAC_CMDCFG_SR			0x00000800	/* Set to reset mode */
++#define  BGMAC_CMDCFG_SR_REVO			0x00000800	/* Set to reset mode, for other revs */
++#define  BGMAC_CMDCFG_SR_REV4			0x00002000	/* Set to reset mode, only for core rev 4 */
++#define  BGMAC_CMDCFG_SR(rev)  ((rev == 4) ? BGMAC_CMDCFG_SR_REV4 : BGMAC_CMDCFG_SR_REVO)
+ #define  BGMAC_CMDCFG_ML			0x00008000	/* Set to activate mac loopback mode */
+ #define  BGMAC_CMDCFG_AE			0x00400000
+ #define  BGMAC_CMDCFG_CFE			0x00800000
+@@ -255,9 +257,34 @@
+ #define  BGMAC_DMA_TX_SUSPEND			0x00000002
+ #define  BGMAC_DMA_TX_LOOPBACK			0x00000004
+ #define  BGMAC_DMA_TX_FLUSH			0x00000010
++#define  BGMAC_DMA_TX_MR_MASK			0x000000C0	/* Multiple outstanding reads */
++#define  BGMAC_DMA_TX_MR_SHIFT			6
++#define   BGMAC_DMA_TX_MR_1			0
++#define   BGMAC_DMA_TX_MR_2			1
+ #define  BGMAC_DMA_TX_PARITY_DISABLE		0x00000800
+ #define  BGMAC_DMA_TX_ADDREXT_MASK		0x00030000
+ #define  BGMAC_DMA_TX_ADDREXT_SHIFT		16
++#define  BGMAC_DMA_TX_BL_MASK			0x001C0000	/* BurstLen bits */
++#define  BGMAC_DMA_TX_BL_SHIFT			18
++#define   BGMAC_DMA_TX_BL_16			0
++#define   BGMAC_DMA_TX_BL_32			1
++#define   BGMAC_DMA_TX_BL_64			2
++#define   BGMAC_DMA_TX_BL_128			3
++#define   BGMAC_DMA_TX_BL_256			4
++#define   BGMAC_DMA_TX_BL_512			5
++#define   BGMAC_DMA_TX_BL_1024			6
++#define  BGMAC_DMA_TX_PC_MASK			0x00E00000	/* Prefetch control */
++#define  BGMAC_DMA_TX_PC_SHIFT			21
++#define   BGMAC_DMA_TX_PC_0			0
++#define   BGMAC_DMA_TX_PC_4			1
++#define   BGMAC_DMA_TX_PC_8			2
++#define   BGMAC_DMA_TX_PC_16			3
++#define  BGMAC_DMA_TX_PT_MASK			0x03000000	/* Prefetch threshold */
++#define  BGMAC_DMA_TX_PT_SHIFT			24
++#define   BGMAC_DMA_TX_PT_1			0
++#define   BGMAC_DMA_TX_PT_2			1
++#define   BGMAC_DMA_TX_PT_4			2
++#define   BGMAC_DMA_TX_PT_8			3
+ #define BGMAC_DMA_TX_INDEX			0x04
+ #define BGMAC_DMA_TX_RINGLO			0x08
+ #define BGMAC_DMA_TX_RINGHI			0x0C
+@@ -285,8 +312,33 @@
+ #define  BGMAC_DMA_RX_DIRECT_FIFO		0x00000100
+ #define  BGMAC_DMA_RX_OVERFLOW_CONT		0x00000400
+ #define  BGMAC_DMA_RX_PARITY_DISABLE		0x00000800
++#define  BGMAC_DMA_RX_MR_MASK			0x000000C0	/* Multiple outstanding reads */
++#define  BGMAC_DMA_RX_MR_SHIFT			6
++#define   BGMAC_DMA_TX_MR_1			0
++#define   BGMAC_DMA_TX_MR_2			1
+ #define  BGMAC_DMA_RX_ADDREXT_MASK		0x00030000
+ #define  BGMAC_DMA_RX_ADDREXT_SHIFT		16
++#define  BGMAC_DMA_RX_BL_MASK			0x001C0000	/* BurstLen bits */
++#define  BGMAC_DMA_RX_BL_SHIFT			18
++#define   BGMAC_DMA_RX_BL_16			0
++#define   BGMAC_DMA_RX_BL_32			1
++#define   BGMAC_DMA_RX_BL_64			2
++#define   BGMAC_DMA_RX_BL_128			3
++#define   BGMAC_DMA_RX_BL_256			4
++#define   BGMAC_DMA_RX_BL_512			5
++#define   BGMAC_DMA_RX_BL_1024			6
++#define  BGMAC_DMA_RX_PC_MASK			0x00E00000	/* Prefetch control */
++#define  BGMAC_DMA_RX_PC_SHIFT			21
++#define   BGMAC_DMA_RX_PC_0			0
++#define   BGMAC_DMA_RX_PC_4			1
++#define   BGMAC_DMA_RX_PC_8			2
++#define   BGMAC_DMA_RX_PC_16			3
++#define  BGMAC_DMA_RX_PT_MASK			0x03000000	/* Prefetch threshold */
++#define  BGMAC_DMA_RX_PT_SHIFT			24
++#define   BGMAC_DMA_RX_PT_1			0
++#define   BGMAC_DMA_RX_PT_2			1
++#define   BGMAC_DMA_RX_PT_4			2
++#define   BGMAC_DMA_RX_PT_8			3
+ #define BGMAC_DMA_RX_INDEX			0x24
+ #define BGMAC_DMA_RX_RINGLO			0x28
+ #define BGMAC_DMA_RX_RINGHI			0x2C

+ 69 - 0
target/linux/generic/patches-3.12/026-bcma-export-bcma_find_core_unit.patch

@@ -0,0 +1,69 @@
+From 0fc9d696e4855f1e03910c431499d68e75904929 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <[email protected]>
+Date: Sun, 10 Nov 2013 20:43:46 +0100
+Subject: [PATCH] bcma: export bcma_find_core_unit()
+
+---
+ drivers/bcma/bcma_private.h |    2 --
+ drivers/bcma/main.c         |   13 +------------
+ include/linux/bcma/bcma.h   |    9 ++++++++-
+ 3 files changed, 9 insertions(+), 15 deletions(-)
+
+--- a/drivers/bcma/bcma_private.h
++++ b/drivers/bcma/bcma_private.h
+@@ -33,8 +33,6 @@ int __init bcma_bus_early_register(struc
+ int bcma_bus_suspend(struct bcma_bus *bus);
+ int bcma_bus_resume(struct bcma_bus *bus);
+ #endif
+-struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+-					u8 unit);
+ 
+ /* scan.c */
+ int bcma_bus_scan(struct bcma_bus *bus);
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -69,18 +69,6 @@ static u16 bcma_cc_core_id(struct bcma_b
+ 	return BCMA_CORE_CHIPCOMMON;
+ }
+ 
+-struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+-{
+-	struct bcma_device *core;
+-
+-	list_for_each_entry(core, &bus->cores, list) {
+-		if (core->id.id == coreid)
+-			return core;
+-	}
+-	return NULL;
+-}
+-EXPORT_SYMBOL_GPL(bcma_find_core);
+-
+ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+ 					u8 unit)
+ {
+@@ -92,6 +80,7 @@ struct bcma_device *bcma_find_core_unit(
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(bcma_find_core_unit);
+ 
+ bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
+ 		     int timeout)
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -418,7 +418,14 @@ static inline void bcma_maskset16(struct
+ 	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
+ }
+ 
+-extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
++extern struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
++					       u8 unit);
++static inline struct bcma_device *bcma_find_core(struct bcma_bus *bus,
++						 u16 coreid)
++{
++	return bcma_find_core_unit(bus, coreid, 0);
++}
++
+ extern bool bcma_core_is_enabled(struct bcma_device *core);
+ extern void bcma_core_disable(struct bcma_device *core, u32 flags);
+ extern int bcma_core_enable(struct bcma_device *core, u32 flags);

+ 26 - 0
target/linux/generic/patches-3.12/772-bgmac-add-supprot-for-BCM4707.patch

@@ -97,6 +97,32 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  }
  
  /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
+@@ -1488,6 +1512,25 @@ static int bgmac_probe(struct bcma_devic
+ 		goto err_netdev_free;
+ 	}
+ 
++	/* Northstar, take all GMAC cores out of reset */
++	if (core->id.id == BCMA_CHIP_ID_BCM4707 ||
++	    core->id.id == BCMA_CHIP_ID_BCM53018) {
++		struct bcma_device *ns_core;
++		int ns_gmac;
++
++		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
++			/* As northstar requirement, we have to reset all GAMCs before
++			 * accessing them. et_probe() call pci_enable_device() for etx
++			 * and do si_core_reset for GAMCx only.	 Then the other three
++			 * GAMCs didn't reset.  We do it here.
++			 */
++			ns_core = bcma_find_core_unit(core->bus, BCMA_CORE_MAC_GBIT, ns_gmac);
++			if (!bcma_core_is_enabled(ns_core)) {
++				bcma_core_enable(ns_core, 0);
++			}
++		}
++	}
++
+ 	bgmac_chip_reset(bgmac);
+ 
+ 	err = bgmac_dma_alloc(bgmac);
 --- a/drivers/net/ethernet/broadcom/bgmac.h
 +++ b/drivers/net/ethernet/broadcom/bgmac.h
 @@ -185,6 +185,7 @@

+ 2 - 2
target/linux/generic/patches-3.12/773-bgmac-add-srab-switch.patch

@@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  /**************************************************
   * BCMA bus ops
   **************************************************/
-@@ -1542,6 +1554,16 @@ static int bgmac_probe(struct bcma_devic
+@@ -1561,6 +1573,16 @@ static int bgmac_probe(struct bcma_devic
  		goto err_dma_free;
  	}
  
@@ -47,7 +47,7 @@ Signed-off-by: Hauke Mehrtens <[email protected]>
  	err = register_netdev(bgmac->net_dev);
  	if (err) {
  		bgmac_err(bgmac, "Cannot register net device\n");
-@@ -1571,6 +1593,10 @@ static void bgmac_remove(struct bcma_dev
+@@ -1590,6 +1612,10 @@ static void bgmac_remove(struct bcma_dev
  {
  	struct bgmac *bgmac = bcma_get_drvdata(core);
  

+ 163 - 0
target/linux/generic/patches-3.12/774-bgmac-add-some-workaround-for-rev-4.patch

@@ -0,0 +1,163 @@
+From ec12b94d22fa8715561bdffe6da0781dac08423e Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <[email protected]>
+Date: Sun, 10 Nov 2013 21:23:57 +0100
+Subject: [PATCH] bgmac: add some workaround for rev 4
+
+---
+ drivers/net/ethernet/broadcom/bgmac.c |    8 ++++----
+ drivers/net/ethernet/broadcom/bgmac.h |    4 +++-
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -97,6 +97,16 @@ static void bgmac_dma_tx_enable(struct b
+ 	u32 ctl;
+ 
+ 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
++	if (bgmac->core->id.rev == 4) {
++		ctl &= ~BGMAC_DMA_TX_BL_MASK;
++		ctl |= BGMAC_DMA_TX_BL_128 << BGMAC_DMA_TX_BL_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_MR_MASK;
++		ctl |= BGMAC_DMA_TX_MR_2 << BGMAC_DMA_TX_MR_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_PC_MASK;
++		ctl |= BGMAC_DMA_TX_PC_16 << BGMAC_DMA_TX_PC_SHIFT;
++		ctl &= ~BGMAC_DMA_TX_PT_MASK;
++		ctl |= BGMAC_DMA_TX_PT_8 << BGMAC_DMA_TX_PT_SHIFT;
++	}
+ 	ctl |= BGMAC_DMA_TX_ENABLE;
+ 	ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
+ 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
+@@ -246,6 +256,17 @@ static void bgmac_dma_rx_enable(struct b
+ 	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
+ 	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
+ 	ctl |= BGMAC_RX_FRAME_OFFSET << BGMAC_DMA_RX_FRAME_OFFSET_SHIFT;
++
++	if (bgmac->core->id.rev == 4) {
++		ctl &= ~BGMAC_DMA_RX_BL_MASK;
++		ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;
++
++		ctl &= ~BGMAC_DMA_RX_PC_MASK;
++		ctl |= BGMAC_DMA_RX_PC_8 << BGMAC_DMA_RX_PC_SHIFT;
++
++		ctl &= ~BGMAC_DMA_RX_PT_MASK;
++		ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
++	}
+ 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, ctl);
+ }
+ 
+@@ -812,13 +833,13 @@ static void bgmac_cmdcfg_maskset(struct
+ 	u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
+ 	u32 new_val = (cmdcfg & mask) | set;
+ 
+-	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR);
++	bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR(bgmac->core->id.rev));
+ 	udelay(2);
+ 
+ 	if (new_val != cmdcfg || force)
+ 		bgmac_write(bgmac, BGMAC_CMDCFG, new_val);
+ 
+-	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR);
++	bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR(bgmac->core->id.rev));
+ 	udelay(2);
+ }
+ 
+@@ -1029,7 +1050,7 @@ static void bgmac_chip_reset(struct bgma
+ 			     BGMAC_CMDCFG_PROM |
+ 			     BGMAC_CMDCFG_NLC |
+ 			     BGMAC_CMDCFG_CFE |
+-			     BGMAC_CMDCFG_SR,
++			     BGMAC_CMDCFG_SR(core->id.rev),
+ 			     false);
+ 
+ 	bgmac_clear_mib(bgmac);
+@@ -1070,7 +1091,7 @@ static void bgmac_enable(struct bgmac *b
+ 
+ 	cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
+ 	bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
+-			     BGMAC_CMDCFG_SR, true);
++			     BGMAC_CMDCFG_SR(bgmac->core->id.rev), true);
+ 	udelay(2);
+ 	cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
+ 	bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);
+--- a/drivers/net/ethernet/broadcom/bgmac.h
++++ b/drivers/net/ethernet/broadcom/bgmac.h
+@@ -194,7 +194,9 @@
+ #define  BGMAC_CMDCFG_TAI			0x00000200
+ #define  BGMAC_CMDCFG_HD			0x00000400	/* Set if in half duplex mode */
+ #define  BGMAC_CMDCFG_HD_SHIFT			10
+-#define  BGMAC_CMDCFG_SR			0x00000800	/* Set to reset mode */
++#define  BGMAC_CMDCFG_SR_REVO			0x00000800	/* Set to reset mode, for other revs */
++#define  BGMAC_CMDCFG_SR_REV4			0x00002000	/* Set to reset mode, only for core rev 4 */
++#define  BGMAC_CMDCFG_SR(rev)  ((rev == 4) ? BGMAC_CMDCFG_SR_REV4 : BGMAC_CMDCFG_SR_REVO)
+ #define  BGMAC_CMDCFG_ML			0x00008000	/* Set to activate mac loopback mode */
+ #define  BGMAC_CMDCFG_AE			0x00400000
+ #define  BGMAC_CMDCFG_CFE			0x00800000
+@@ -255,9 +257,34 @@
+ #define  BGMAC_DMA_TX_SUSPEND			0x00000002
+ #define  BGMAC_DMA_TX_LOOPBACK			0x00000004
+ #define  BGMAC_DMA_TX_FLUSH			0x00000010
++#define  BGMAC_DMA_TX_MR_MASK			0x000000C0	/* Multiple outstanding reads */
++#define  BGMAC_DMA_TX_MR_SHIFT			6
++#define   BGMAC_DMA_TX_MR_1			0
++#define   BGMAC_DMA_TX_MR_2			1
+ #define  BGMAC_DMA_TX_PARITY_DISABLE		0x00000800
+ #define  BGMAC_DMA_TX_ADDREXT_MASK		0x00030000
+ #define  BGMAC_DMA_TX_ADDREXT_SHIFT		16
++#define  BGMAC_DMA_TX_BL_MASK			0x001C0000	/* BurstLen bits */
++#define  BGMAC_DMA_TX_BL_SHIFT			18
++#define   BGMAC_DMA_TX_BL_16			0
++#define   BGMAC_DMA_TX_BL_32			1
++#define   BGMAC_DMA_TX_BL_64			2
++#define   BGMAC_DMA_TX_BL_128			3
++#define   BGMAC_DMA_TX_BL_256			4
++#define   BGMAC_DMA_TX_BL_512			5
++#define   BGMAC_DMA_TX_BL_1024			6
++#define  BGMAC_DMA_TX_PC_MASK			0x00E00000	/* Prefetch control */
++#define  BGMAC_DMA_TX_PC_SHIFT			21
++#define   BGMAC_DMA_TX_PC_0			0
++#define   BGMAC_DMA_TX_PC_4			1
++#define   BGMAC_DMA_TX_PC_8			2
++#define   BGMAC_DMA_TX_PC_16			3
++#define  BGMAC_DMA_TX_PT_MASK			0x03000000	/* Prefetch threshold */
++#define  BGMAC_DMA_TX_PT_SHIFT			24
++#define   BGMAC_DMA_TX_PT_1			0
++#define   BGMAC_DMA_TX_PT_2			1
++#define   BGMAC_DMA_TX_PT_4			2
++#define   BGMAC_DMA_TX_PT_8			3
+ #define BGMAC_DMA_TX_INDEX			0x04
+ #define BGMAC_DMA_TX_RINGLO			0x08
+ #define BGMAC_DMA_TX_RINGHI			0x0C
+@@ -285,8 +312,33 @@
+ #define  BGMAC_DMA_RX_DIRECT_FIFO		0x00000100
+ #define  BGMAC_DMA_RX_OVERFLOW_CONT		0x00000400
+ #define  BGMAC_DMA_RX_PARITY_DISABLE		0x00000800
++#define  BGMAC_DMA_RX_MR_MASK			0x000000C0	/* Multiple outstanding reads */
++#define  BGMAC_DMA_RX_MR_SHIFT			6
++#define   BGMAC_DMA_TX_MR_1			0
++#define   BGMAC_DMA_TX_MR_2			1
+ #define  BGMAC_DMA_RX_ADDREXT_MASK		0x00030000
+ #define  BGMAC_DMA_RX_ADDREXT_SHIFT		16
++#define  BGMAC_DMA_RX_BL_MASK			0x001C0000	/* BurstLen bits */
++#define  BGMAC_DMA_RX_BL_SHIFT			18
++#define   BGMAC_DMA_RX_BL_16			0
++#define   BGMAC_DMA_RX_BL_32			1
++#define   BGMAC_DMA_RX_BL_64			2
++#define   BGMAC_DMA_RX_BL_128			3
++#define   BGMAC_DMA_RX_BL_256			4
++#define   BGMAC_DMA_RX_BL_512			5
++#define   BGMAC_DMA_RX_BL_1024			6
++#define  BGMAC_DMA_RX_PC_MASK			0x00E00000	/* Prefetch control */
++#define  BGMAC_DMA_RX_PC_SHIFT			21
++#define   BGMAC_DMA_RX_PC_0			0
++#define   BGMAC_DMA_RX_PC_4			1
++#define   BGMAC_DMA_RX_PC_8			2
++#define   BGMAC_DMA_RX_PC_16			3
++#define  BGMAC_DMA_RX_PT_MASK			0x03000000	/* Prefetch threshold */
++#define  BGMAC_DMA_RX_PT_SHIFT			24
++#define   BGMAC_DMA_RX_PT_1			0
++#define   BGMAC_DMA_RX_PT_2			1
++#define   BGMAC_DMA_RX_PT_4			2
++#define   BGMAC_DMA_RX_PT_8			3
+ #define BGMAC_DMA_RX_INDEX			0x24
+ #define BGMAC_DMA_RX_RINGLO			0x28
+ #define BGMAC_DMA_RX_RINGHI			0x2C