kernel: bgmac: make it send and receive some packages on BCM4708
authorHauke Mehrtens <hauke@hauke-m.de>
Mon, 11 Nov 2013 00:13:31 +0000 (00:13 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 11 Nov 2013 00:13:31 +0000 (00:13 +0000)
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 <hauke@hauke-m.de>
SVN-Revision: 38714

target/linux/generic/patches-3.10/026-bcma-export-bcma_find_core_unit.patch [new file with mode: 0644]
target/linux/generic/patches-3.10/772-bgmac-add-supprot-for-BCM4707.patch
target/linux/generic/patches-3.10/773-bgmac-add-srab-switch.patch
target/linux/generic/patches-3.10/774-bgmac-add-some-workaround-for-rev-4.patch [new file with mode: 0644]
target/linux/generic/patches-3.12/026-bcma-export-bcma_find_core_unit.patch [new file with mode: 0644]
target/linux/generic/patches-3.12/772-bgmac-add-supprot-for-BCM4707.patch
target/linux/generic/patches-3.12/773-bgmac-add-srab-switch.patch
target/linux/generic/patches-3.12/774-bgmac-add-some-workaround-for-rev-4.patch [new file with mode: 0644]

diff --git a/target/linux/generic/patches-3.10/026-bcma-export-bcma_find_core_unit.patch b/target/linux/generic/patches-3.10/026-bcma-export-bcma_find_core_unit.patch
new file mode 100644 (file)
index 0000000..86bce67
--- /dev/null
@@ -0,0 +1,69 @@
+From 0fc9d696e4855f1e03910c431499d68e75904929 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+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);
index eb1708a2c4e4dd395635eeeb9ff22fccb6202ffc..a4e51774d5ffae79230a6e43c4fb8d0d5d27359b 100644 (file)
@@ -97,6 +97,32 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  }
  
  /* 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 @@
index e5ec78d59f604b98e4b359fa91a7490a639e5720..be253064b11d2946422143319ff79d7711621514 100644 (file)
@@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  /**************************************************
   * 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 <hauke@hauke-m.de>
        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);
  
diff --git a/target/linux/generic/patches-3.10/774-bgmac-add-some-workaround-for-rev-4.patch b/target/linux/generic/patches-3.10/774-bgmac-add-some-workaround-for-rev-4.patch
new file mode 100644 (file)
index 0000000..4e1a449
--- /dev/null
@@ -0,0 +1,163 @@
+From ec12b94d22fa8715561bdffe6da0781dac08423e Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+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
diff --git a/target/linux/generic/patches-3.12/026-bcma-export-bcma_find_core_unit.patch b/target/linux/generic/patches-3.12/026-bcma-export-bcma_find_core_unit.patch
new file mode 100644 (file)
index 0000000..86bce67
--- /dev/null
@@ -0,0 +1,69 @@
+From 0fc9d696e4855f1e03910c431499d68e75904929 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+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);
index eb1708a2c4e4dd395635eeeb9ff22fccb6202ffc..a4e51774d5ffae79230a6e43c4fb8d0d5d27359b 100644 (file)
@@ -97,6 +97,32 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  }
  
  /* 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 @@
index e5ec78d59f604b98e4b359fa91a7490a639e5720..be253064b11d2946422143319ff79d7711621514 100644 (file)
@@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  /**************************************************
   * 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 <hauke@hauke-m.de>
        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);
  
diff --git a/target/linux/generic/patches-3.12/774-bgmac-add-some-workaround-for-rev-4.patch b/target/linux/generic/patches-3.12/774-bgmac-add-some-workaround-for-rev-4.patch
new file mode 100644 (file)
index 0000000..4e1a449
--- /dev/null
@@ -0,0 +1,163 @@
+From ec12b94d22fa8715561bdffe6da0781dac08423e Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+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