Commit 62a9fa01 authored by David S. Miller's avatar David S. Miller

Merge branch 'bcmgenet-add-support-for-GENETv5'

Doug Berger says:

====================
net: bcmgenet: add support for GENETv5

This collection of patches contains changes related to adding
support for the BCM7260, BCM7268, and BCM7271 devices that
contain a new version of the GENET MAC IP block (v5) and a new
fast ethernet (10/100BASE-T) internal PHY.

These patches were originally developed on top of the bug fixes
of the "[PATCH v2 net 0/8] net: bcmgenet: minor bug fixes" patch
set previously accepted into the net repository, but this
submission is designed to be applied to the current net-next
that does not yet include them. As a result there will be some
merge conflicts that I would be happy to help resolve if desired.

Specifically, conflicts should occur with these patches from the
minor bug fixes set:
[PATCH v2 net 3/8] net: bcmgenet: reserved phy revisions must be checked first
[PATCH v2 net 5/8] net: bcmgenet: synchronize irq0 status between the isr and task
[PATCH v2 net 8/8] net: bcmgenet: decouple flow control from bcmgenet_tx_reclaim
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c55fa3cc 42138085
......@@ -2,11 +2,14 @@
Required properties:
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
"brcm,genet-v3", "brcm,genet-v4".
"brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5".
- reg: address and length of the register set for the device
- interrupts: must be two cells, the first cell is the general purpose
interrupt line, while the second cell is the interrupt for the ring
RX and TX queues operating in ring mode
- interrupts and/or interrupts-extended: must be two cells, the first cell
is the general purpose interrupt line, while the second cell is the
interrupt for the ring RX and TX queues operating in ring mode. An
optional third interrupt cell for Wake-on-LAN can be specified.
See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
for information on the property specifics.
- phy-mode: see ethernet.txt file in the same directory
- #address-cells: should be 1
- #size-cells: should be 1
......@@ -29,15 +32,15 @@ Optional properties:
Required child nodes:
- mdio bus node: this node should always be present regarless of the PHY
- mdio bus node: this node should always be present regardless of the PHY
configuration of the GENET instance
MDIO bus node required properties:
- compatible: should contain one of "brcm,genet-mdio-v1", "brcm,genet-mdio-v2"
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", the version has to match the
parent node compatible property (e.g: brcm,genet-v4 pairs with
brcm,genet-mdio-v4)
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", "brcm,genet-mdio-v5", the version
has to match the parent node compatible property (e.g: brcm,genet-v4 pairs
with brcm,genet-mdio-v4)
- reg: address and length relative to the parent node base register address
- #address-cells: address cell for MDIO bus addressing, should be 1
- #size-cells: size of the cells for MDIO bus addressing, should be 0
......
......@@ -2,8 +2,9 @@
Required properties:
- compatible: should one from "brcm,genet-mdio-v1", "brcm,genet-mdio-v2",
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4" or "brcm,unimac-mdio"
- reg: address and length of the regsiter set for the device, first one is the
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", "brcm,genet-mdio-v5" or
"brcm,unimac-mdio"
- reg: address and length of the register set for the device, first one is the
base register, and the second one is optional and for indirect accesses to
larger than 16-bits MDIO transactions
- reg-names: name(s) of the register must be "mdio" and optional "mdio_indir_rw"
......
/*
* Copyright (c) 2014 Broadcom Corporation
* Copyright (c) 2014-2017 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -351,8 +351,14 @@ struct bcmgenet_mib_counters {
#define EXT_PWR_DN_EN_LD (1 << 3)
#define EXT_ENERGY_DET (1 << 4)
#define EXT_IDDQ_FROM_PHY (1 << 5)
#define EXT_IDDQ_GLBL_PWR (1 << 7)
#define EXT_PHY_RESET (1 << 8)
#define EXT_ENERGY_DET_MASK (1 << 12)
#define EXT_PWR_DOWN_PHY_TX (1 << 16)
#define EXT_PWR_DOWN_PHY_RX (1 << 17)
#define EXT_PWR_DOWN_PHY_SD (1 << 18)
#define EXT_PWR_DOWN_PHY_RD (1 << 19)
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
#define EXT_RGMII_OOB_CTRL 0x0C
#define RGMII_LINK (1 << 4)
......@@ -495,13 +501,15 @@ enum bcmgenet_version {
GENET_V1 = 1,
GENET_V2,
GENET_V3,
GENET_V4
GENET_V4,
GENET_V5
};
#define GENET_IS_V1(p) ((p)->version == GENET_V1)
#define GENET_IS_V2(p) ((p)->version == GENET_V2)
#define GENET_IS_V3(p) ((p)->version == GENET_V3)
#define GENET_IS_V4(p) ((p)->version == GENET_V4)
#define GENET_IS_V5(p) ((p)->version == GENET_V5)
/* Hardware flags */
#define GENET_HAS_40BITS (1 << 0)
......
/*
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
*
* Copyright (c) 2014 Broadcom Corporation
* Copyright (c) 2014-2017 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -127,7 +127,6 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
enum bcmgenet_power_mode mode)
{
struct net_device *dev = priv->dev;
u32 cpu_mask_clear;
int retries = 0;
u32 reg;
......@@ -173,18 +172,12 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
}
/* Enable the MPD interrupt */
cpu_mask_clear = UMAC_IRQ_MPD_R;
bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR);
return 0;
}
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
enum bcmgenet_power_mode mode)
{
u32 cpu_mask_set;
u32 reg;
if (mode != GENET_POWER_WOL_MAGIC) {
......@@ -201,10 +194,4 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
reg &= ~CMD_CRC_FWD;
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
priv->crc_fwd_en = 0;
/* Stop monitoring magic packet IRQ */
cpu_mask_set = UMAC_IRQ_MPD_R;
/* Stop monitoring magic packet IRQ */
bcmgenet_intrl2_0_writel(priv, cpu_mask_set, INTRL2_CPU_MASK_SET);
}
/*
* Broadcom GENET MDIO routines
*
* Copyright (c) 2014 Broadcom Corporation
* Copyright (c) 2014-2017 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -195,29 +195,31 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
u32 reg = 0;
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
if (!GENET_IS_V4(priv))
return;
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
if (enable) {
reg &= ~EXT_CK25_DIS;
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
reg |= EXT_GPHY_RESET;
if (GENET_IS_V4(priv)) {
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
if (enable) {
reg &= ~EXT_CK25_DIS;
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
reg |= EXT_GPHY_RESET;
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg &= ~EXT_GPHY_RESET;
} else {
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
EXT_GPHY_RESET;
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg |= EXT_CK25_DIS;
}
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg &= ~EXT_GPHY_RESET;
udelay(60);
} else {
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN | EXT_GPHY_RESET;
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
mdelay(1);
reg |= EXT_CK25_DIS;
}
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
udelay(60);
}
static void bcmgenet_internal_phy_setup(struct net_device *dev)
......@@ -227,10 +229,12 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
/* Power up PHY */
bcmgenet_phy_power_set(dev, true);
/* enable APD */
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_PWR_DN_EN_LD;
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
if (!GENET_IS_V5(priv)) {
/* enable APD */
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_PWR_DN_EN_LD;
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
}
bcmgenet_mii_reset(dev);
}
......@@ -238,10 +242,12 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
{
u32 reg;
/* Speed settings are set in bcmgenet_mii_setup() */
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
reg |= LED_ACT_SOURCE_MAC;
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
if (!GENET_IS_V5(priv)) {
/* Speed settings are set in bcmgenet_mii_setup() */
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
reg |= LED_ACT_SOURCE_MAC;
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
}
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
fixed_phy_set_link_update(priv->phydev,
......
/*
* Copyright (C) 2015 Broadcom Corporation
* Copyright (C) 2015-2017 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -221,9 +221,9 @@ int bcm_phy_set_eee(struct phy_device *phydev, bool enable)
return val;
if (enable)
val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
val |= (MDIO_EEE_100TX | MDIO_EEE_1000T);
else
val &= ~(MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
val &= ~(MDIO_EEE_100TX | MDIO_EEE_1000T);
phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
MDIO_MMD_AN, (u32)val);
......
/*
* Broadcom BCM7xxx internal transceivers support.
*
* Copyright (C) 2014, Broadcom Corporation
* Copyright (C) 2014-2017 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -19,7 +19,7 @@
/* Broadcom BCM7xxx internal PHY registers */
/* 40nm only register definitions */
/* EPHY only register definitions */
#define MII_BCM7XXX_100TX_AUX_CTL 0x10
#define MII_BCM7XXX_100TX_FALSE_CAR 0x13
#define MII_BCM7XXX_100TX_DISC 0x14
......@@ -27,6 +27,19 @@
#define MII_BCM7XXX_64CLK_MDIO BIT(12)
#define MII_BCM7XXX_TEST 0x1f
#define MII_BCM7XXX_SHD_MODE_2 BIT(2)
#define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe
#define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf
#define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a
#define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3
#define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6
#define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400
#define MII_BCM7XXX_SHD_3_AN_STAT 0xb
#define MII_BCM7XXX_AN_NULL_MSG_EN BIT(0)
#define MII_BCM7XXX_AN_EEE_EN BIT(1)
#define MII_BCM7XXX_SHD_3_EEE_THRESH 0xe
#define MII_BCM7XXX_EEE_THRESH_DEF 0x50
#define MII_BCM7XXX_SHD_3_TL4 0x23
#define MII_BCM7XXX_TL4_RST_MSK (BIT(2) | BIT(1))
/* 28nm only register definitions */
#define MISC_ADDR(base, channel) base, channel
......@@ -286,6 +299,181 @@ static int phy_set_clr_bits(struct phy_device *dev, int location,
return v;
}
static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
{
int ret;
/* set shadow mode 2 */
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
MII_BCM7XXX_SHD_MODE_2, 0);
if (ret < 0)
return ret;
/* Set current trim values INT_trim = -1, Ext_trim =0 */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
if (ret < 0)
goto reset_shadow_mode;
/* Cal reset */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_TL4);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
MII_BCM7XXX_TL4_RST_MSK, 0);
if (ret < 0)
goto reset_shadow_mode;
/* Cal reset disable */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_TL4);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0, MII_BCM7XXX_TL4_RST_MSK);
if (ret < 0)
goto reset_shadow_mode;
reset_shadow_mode:
/* reset shadow mode 2 */
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
MII_BCM7XXX_SHD_MODE_2);
if (ret < 0)
return ret;
return 0;
}
/* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
{
int ret;
/* set shadow mode 1 */
ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
MII_BRCM_FET_BT_SRE, 0);
if (ret < 0)
return ret;
/* Enable auto-power down */
ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
MII_BRCM_FET_SHDW_AS2_APDE, 0);
if (ret < 0)
return ret;
/* reset shadow mode 1 */
ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
MII_BRCM_FET_BT_SRE);
if (ret < 0)
return ret;
return 0;
}
static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
{
int ret;
/* set shadow mode 2 */
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
MII_BCM7XXX_SHD_MODE_2, 0);
if (ret < 0)
return ret;
/* Advertise supported modes */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_AN_EEE_ADV);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
MDIO_EEE_100TX);
if (ret < 0)
goto reset_shadow_mode;
/* Restore Defaults */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_PCS_CTRL_2);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
MII_BCM7XXX_PCS_CTRL_2_DEF);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_EEE_THRESH);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
MII_BCM7XXX_EEE_THRESH_DEF);
if (ret < 0)
goto reset_shadow_mode;
/* Enable EEE autonegotiation */
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
MII_BCM7XXX_SHD_3_AN_STAT);
if (ret < 0)
goto reset_shadow_mode;
ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
(MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
if (ret < 0)
goto reset_shadow_mode;
reset_shadow_mode:
/* reset shadow mode 2 */
ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
MII_BCM7XXX_SHD_MODE_2);
if (ret < 0)
return ret;
/* Restart autoneg */
phy_write(phydev, MII_BMCR,
(BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
return 0;
}
static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
{
u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
int ret = 0;
pr_info_once("%s: %s PHY revision: 0x%02x\n",
phydev_name(phydev), phydev->drv->name, rev);
/* Dummy read to a register to workaround a possible issue upon reset
* where the internal inverter may not allow the first MDIO transaction
* to pass the MDIO management controller and make us return 0xffff for
* such reads.
*/
phy_read(phydev, MII_BMSR);
/* Apply AFE software work-around if necessary */
if (rev == 0x01) {
ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
if (ret)
return ret;
}
ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
if (ret)
return ret;
return bcm7xxx_28nm_ephy_apd_enable(phydev);
}
static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
{
int ret;
/* Re-apply workarounds coming out suspend/resume */
ret = bcm7xxx_28nm_ephy_config_init(phydev);
if (ret)
return ret;
return genphy_config_aneg(phydev);
}
static int bcm7xxx_config_init(struct phy_device *phydev)
{
int ret;
......@@ -434,6 +622,23 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
.probe = bcm7xxx_28nm_probe, \
}
#define BCM7XXX_28NM_EPHY(_oui, _name) \
{ \
.phy_id = (_oui), \
.phy_id_mask = 0xfffffff0, \
.name = _name, \
.features = PHY_BASIC_FEATURES, \
.flags = PHY_IS_INTERNAL, \
.config_init = bcm7xxx_28nm_ephy_config_init, \
.config_aneg = genphy_config_aneg, \
.read_status = genphy_read_status, \
.resume = bcm7xxx_28nm_ephy_resume, \
.get_sset_count = bcm_phy_get_sset_count, \
.get_strings = bcm_phy_get_strings, \
.get_stats = bcm7xxx_28nm_get_phy_stats, \
.probe = bcm7xxx_28nm_probe, \
}
#define BCM7XXX_40NM_EPHY(_oui, _name) \
{ \
.phy_id = (_oui), \
......@@ -450,6 +655,9 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
static struct phy_driver bcm7xxx_driver[] = {
BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
......@@ -466,6 +674,9 @@ static struct phy_driver bcm7xxx_driver[] = {
static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
{ PHY_ID_BCM7250, 0xfffffff0, },
{ PHY_ID_BCM7260, 0xfffffff0, },
{ PHY_ID_BCM7268, 0xfffffff0, },
{ PHY_ID_BCM7271, 0xfffffff0, },
{ PHY_ID_BCM7278, 0xfffffff0, },
{ PHY_ID_BCM7364, 0xfffffff0, },
{ PHY_ID_BCM7366, 0xfffffff0, },
......
/*
* Broadcom UniMAC MDIO bus controller driver
*
* Copyright (C) 2014, Broadcom Corporation
* Copyright (C) 2014-2017 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -228,6 +228,7 @@ static int unimac_mdio_remove(struct platform_device *pdev)
}
static const struct of_device_id unimac_mdio_ids[] = {
{ .compatible = "brcm,genet-mdio-v5", },
{ .compatible = "brcm,genet-mdio-v4", },
{ .compatible = "brcm,genet-mdio-v3", },
{ .compatible = "brcm,genet-mdio-v2", },
......
......@@ -25,6 +25,9 @@
#define PHY_ID_BCM57780 0x03625d90
#define PHY_ID_BCM7250 0xae025280
#define PHY_ID_BCM7260 0xae025190
#define PHY_ID_BCM7268 0xae025090
#define PHY_ID_BCM7271 0xae0253b0
#define PHY_ID_BCM7278 0xae0251a0
#define PHY_ID_BCM7364 0xae025260
#define PHY_ID_BCM7366 0x600d8490
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment