net: bgmac: support Ethernet core on BCM53573 SoCs
authorRafał Miłecki <rafal@milecki.pl>
Wed, 17 Aug 2016 21:00:30 +0000 (23:00 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Aug 2016 06:36:07 +0000 (23:36 -0700)
BCM53573 is a new series of Broadcom's SoCs. It's based on ARM and can
be found in two packages (versions): BCM53573 and BCM47189. It shares
some code with the Northstar family, but also requires some new quirks.

First of all there can be up to 2 Ethernet cores on this SoC. If that is
the case, they are connected to two different switch ports allowing some
more complex/optimized setups. It seems the second unit doesn't come
fully configured and requires some IRQ quirk.

Other than that only the first core is connected to the PHY. For the
second one we have to register fixed PHY (similarly to the Northstar),
otherwise generic PHY driver would get some invalid info.

This has been successfully tested on Tenda AC9 (BCM47189B0).

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bgmac-bcma.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bgmac.h
include/linux/bcma/bcma.h
include/linux/bcma/bcma_regs.h

index 9a9745c4047c3757c4b1733dae9d5908db44baa1..3bc0a04df107fcdbc1148be7c2dd90716d641a32 100644 (file)
@@ -92,6 +92,7 @@ MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
 static int bgmac_probe(struct bcma_device *core)
 {
+       struct bcma_chipinfo *ci = &core->bus->chipinfo;
        struct ssb_sprom *sprom = &core->bus->sprom;
        struct mii_bus *mii_bus;
        struct bgmac *bgmac;
@@ -157,7 +158,8 @@ static int bgmac_probe(struct bcma_device *core)
        dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
                 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
 
-       if (!bgmac_is_bcm4707_family(core)) {
+       if (!bgmac_is_bcm4707_family(core) &&
+           !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
                mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr);
                if (!IS_ERR(mii_bus)) {
                        err = PTR_ERR(mii_bus);
@@ -230,6 +232,21 @@ static int bgmac_probe(struct bcma_device *core)
                bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
                bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
                break;
+       case BCMA_CHIP_ID_BCM53573:
+               bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
+               bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
+               if (ci->pkg == BCMA_PKG_ID_BCM47189)
+                       bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
+               if (core->core_unit == 0) {
+                       bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE;
+                       if (ci->pkg == BCMA_PKG_ID_BCM47189)
+                               bgmac->feature_flags |=
+                                       BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII;
+               } else if (core->core_unit == 1) {
+                       bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6;
+                       bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII;
+               }
+               break;
        default:
                bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
                bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
index c4751ece76f677998af0fb90a4a5e75c7361a55e..63ef72355833e01c3ebfefde97f65ff1a5b7e525 100644 (file)
@@ -940,6 +940,27 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
                bgmac_cco_ctl_maskset(bgmac, 1, ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
                                                  BGMAC_CHIPCTL_1_SW_TYPE_MASK),
                                      sw_type);
+       } else if (bgmac->feature_flags & BGMAC_FEAT_CC4_IF_SW_TYPE) {
+               u32 sw_type = BGMAC_CHIPCTL_4_IF_TYPE_MII |
+                             BGMAC_CHIPCTL_4_SW_TYPE_EPHY;
+               u8 et_swtype = 0;
+               char buf[4];
+
+               if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
+                       if (kstrtou8(buf, 0, &et_swtype))
+                               dev_err(bgmac->dev, "Failed to parse et_swtype (%s)\n",
+                                       buf);
+                       sw_type = (et_swtype & 0x0f) << 12;
+               } else if (bgmac->feature_flags & BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII) {
+                       sw_type = BGMAC_CHIPCTL_4_IF_TYPE_RGMII |
+                                 BGMAC_CHIPCTL_4_SW_TYPE_RGMII;
+               }
+               bgmac_cco_ctl_maskset(bgmac, 4, ~(BGMAC_CHIPCTL_4_IF_TYPE_MASK |
+                                                 BGMAC_CHIPCTL_4_SW_TYPE_MASK),
+                                     sw_type);
+       } else if (bgmac->feature_flags & BGMAC_FEAT_CC7_IF_TYPE_RGMII) {
+               bgmac_cco_ctl_maskset(bgmac, 7, ~BGMAC_CHIPCTL_7_IF_TYPE_MASK,
+                                     BGMAC_CHIPCTL_7_IF_TYPE_RGMII);
        }
 
        if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
@@ -1467,6 +1488,10 @@ int bgmac_enet_probe(struct bgmac *info)
         */
        bgmac_clk_enable(bgmac, 0);
 
+       /* This seems to be fixing IRQ by assigning OOB #6 to the core */
+       if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
+               bgmac_idm_write(bgmac, BCMA_OOB_SEL_OUT_A30, 0x86);
+
        bgmac_chip_reset(bgmac);
 
        err = bgmac_dma_alloc(bgmac);
index 24a250267b885ca33832f5ccf0f9a58fd5be5b19..80836b4c9f3814cf115f85a8eb093e54538acd99 100644 (file)
 #define BGMAC_CHIPCTL_1_SW_TYPE_RGMII          0x000000C0
 #define BGMAC_CHIPCTL_1_RXC_DLL_BYPASS         0x00010000
 
+#define BGMAC_CHIPCTL_4_IF_TYPE_MASK           0x00003000
+#define BGMAC_CHIPCTL_4_IF_TYPE_RMII           0x00000000
+#define BGMAC_CHIPCTL_4_IF_TYPE_MII            0x00001000
+#define BGMAC_CHIPCTL_4_IF_TYPE_RGMII          0x00002000
+#define BGMAC_CHIPCTL_4_SW_TYPE_MASK           0x0000C000
+#define BGMAC_CHIPCTL_4_SW_TYPE_EPHY           0x00000000
+#define BGMAC_CHIPCTL_4_SW_TYPE_EPHYMII                0x00004000
+#define BGMAC_CHIPCTL_4_SW_TYPE_EPHYRMII       0x00008000
+#define BGMAC_CHIPCTL_4_SW_TYPE_RGMII          0x0000C000
+
+#define BGMAC_CHIPCTL_7_IF_TYPE_MASK           0x000000C0
+#define BGMAC_CHIPCTL_7_IF_TYPE_RMII           0x00000000
+#define BGMAC_CHIPCTL_7_IF_TYPE_MII            0x00000040
+#define BGMAC_CHIPCTL_7_IF_TYPE_RGMII          0x00000080
+
 #define BGMAC_WEIGHT   64
 
 #define ETHER_MAX_LEN   1518
 #define BGMAC_FEAT_NO_CLR_MIB          BIT(13)
 #define BGMAC_FEAT_FORCE_SPEED_2500    BIT(14)
 #define BGMAC_FEAT_CMDCFG_SR_REV4      BIT(15)
+#define BGMAC_FEAT_IRQ_ID_OOB_6                BIT(16)
+#define BGMAC_FEAT_CC4_IF_SW_TYPE      BIT(17)
+#define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII        BIT(18)
+#define BGMAC_FEAT_CC7_IF_TYPE_RGMII   BIT(19)
 
 struct bgmac_slot_info {
        union {
index 3db25df396cbb88d2135874818f4fb38a71b2eee..8eeedb2db9242ec0101d5c390db02cc51d5999e1 100644 (file)
@@ -205,6 +205,9 @@ struct bcma_host_ops {
 #define  BCMA_PKG_ID_BCM4709   0
 #define BCMA_CHIP_ID_BCM47094  53030
 #define BCMA_CHIP_ID_BCM53018  53018
+#define BCMA_CHIP_ID_BCM53573  53573
+#define  BCMA_PKG_ID_BCM53573  0
+#define  BCMA_PKG_ID_BCM47189  1
 
 /* Board types (on PCI usually equals to the subsystem dev id) */
 /* BCM4313 */
index ebd5c1fcdea4cfa0d6fa57a3cc428bf538f02eb4..c607fce6aadd59aa765ae255d24e741a4b8458fa 100644 (file)
@@ -23,6 +23,7 @@
 #define  BCMA_CLKCTLST_4328A0_HAVEALP  0x00020000 /* 4328a0 has reversed bits */
 
 /* Agent registers (common for every core) */
+#define BCMA_OOB_SEL_OUT_A30           0x0100
 #define BCMA_IOCTL                     0x0408 /* IO control */
 #define  BCMA_IOCTL_CLK                        0x0001
 #define  BCMA_IOCTL_FGC                        0x0002