Skip to content

Commit

Permalink
Merge branch 'net-phy-Move-Omega-PHY-entry-to-Cygnus-PHY-driver'
Browse files Browse the repository at this point in the history
Florian Fainelli says:

====================
net: phy: Move Omega PHY entry to Cygnus PHY driver

In order to pave the way for adding some specific Omega PHY features
that may not be desirable on other products covered by the bcm7xxx PHY
driver, split the Omega PHY entry into the Cygnus PHY driver such that
the PHY drivers are reflective of product lines/business units
maintaining them within Broadcom.

No functional changes intended.
====================

Acked-by: Arun Parameswaran <arun.parameswaran@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 21, 2019
2 parents 02afc7a + 17cc982 commit 83b038d
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 75 deletions.
5 changes: 3 additions & 2 deletions drivers/net/phy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,13 @@ config BCM87XX_PHY

config BCM_CYGNUS_PHY
tristate "Broadcom Cygnus SoC internal PHY"
depends on ARCH_BCM_CYGNUS || COMPILE_TEST
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on MDIO_BCM_IPROC
tristate "Broadcom Cygnus/Omega SoC internal PHY"
select BCM_NET_PHYLIB
---help---
This PHY driver is for the 1G internal PHYs of the Broadcom
Cygnus Family SoC.
Cygnus and Omega Family SoC.

Currently supports internal PHY's used in the BCM11300,
BCM11320, BCM11350, BCM11360, BCM58300, BCM58302,
Expand Down
147 changes: 146 additions & 1 deletion drivers/net/phy/bcm-cygnus.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include <linux/netdevice.h>
#include <linux/phy.h>

struct bcm_omega_phy_priv {
u64 *stats;
};

/* Broadcom Cygnus Phy specific registers */
#define MII_BCM_CYGNUS_AFE_VDAC_ICTRL_0 0x91E5 /* VDAL Control register */

Expand Down Expand Up @@ -121,6 +125,130 @@ static int bcm_cygnus_resume(struct phy_device *phydev)
return genphy_config_aneg(phydev);
}

static int bcm_omega_config_init(struct phy_device *phydev)
{
u8 count, rev;
int ret = 0;

rev = phydev->phy_id & ~phydev->drv->phy_id_mask;

pr_info_once("%s: %s PHY revision: 0x%02x\n",
phydev_name(phydev), phydev->drv->name, rev);

/* Dummy read to a register to workaround an 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);

switch (rev) {
case 0x00:
ret = bcm_phy_28nm_a0b0_afe_config_init(phydev);
break;
default:
break;
}

if (ret)
return ret;

ret = bcm_phy_downshift_get(phydev, &count);
if (ret)
return ret;

/* Only enable EEE if Wirespeed/downshift is disabled */
ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
if (ret)
return ret;

return bcm_phy_enable_apd(phydev, true);
}

static int bcm_omega_resume(struct phy_device *phydev)
{
int ret;

/* Re-apply workarounds coming out suspend/resume */
ret = bcm_omega_config_init(phydev);
if (ret)
return ret;

/* 28nm Gigabit PHYs come out of reset without any half-duplex
* or "hub" compliant advertised mode, fix that. This does not
* cause any problems with the PHY library since genphy_config_aneg()
* gracefully handles auto-negotiated and forced modes.
*/
return genphy_config_aneg(phydev);
}

static int bcm_omega_get_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, void *data)
{
switch (tuna->id) {
case ETHTOOL_PHY_DOWNSHIFT:
return bcm_phy_downshift_get(phydev, (u8 *)data);
default:
return -EOPNOTSUPP;
}
}

static int bcm_omega_set_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna,
const void *data)
{
u8 count = *(u8 *)data;
int ret;

switch (tuna->id) {
case ETHTOOL_PHY_DOWNSHIFT:
ret = bcm_phy_downshift_set(phydev, count);
break;
default:
return -EOPNOTSUPP;
}

if (ret)
return ret;

/* Disable EEE advertisement since this prevents the PHY
* from successfully linking up, trigger auto-negotiation restart
* to let the MAC decide what to do.
*/
ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
if (ret)
return ret;

return genphy_restart_aneg(phydev);
}

static void bcm_omega_get_phy_stats(struct phy_device *phydev,
struct ethtool_stats *stats, u64 *data)
{
struct bcm_omega_phy_priv *priv = phydev->priv;

bcm_phy_get_stats(phydev, priv->stats, stats, data);
}

static int bcm_omega_probe(struct phy_device *phydev)
{
struct bcm_omega_phy_priv *priv;

priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

phydev->priv = priv;

priv->stats = devm_kcalloc(&phydev->mdio.dev,
bcm_phy_get_sset_count(phydev), sizeof(u64),
GFP_KERNEL);
if (!priv->stats)
return -ENOMEM;

return 0;
}

static struct phy_driver bcm_cygnus_phy_driver[] = {
{
.phy_id = PHY_ID_BCM_CYGNUS,
Expand All @@ -132,10 +260,27 @@ static struct phy_driver bcm_cygnus_phy_driver[] = {
.config_intr = bcm_phy_config_intr,
.suspend = genphy_suspend,
.resume = bcm_cygnus_resume,
} };
}, {
.phy_id = PHY_ID_BCM_OMEGA,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom Omega Combo GPHY",
.features = PHY_GBIT_FEATURES,
.flags = PHY_IS_INTERNAL,
.config_init = bcm_omega_config_init,
.suspend = genphy_suspend,
.resume = bcm_omega_resume,
.get_tunable = bcm_omega_get_tunable,
.set_tunable = bcm_omega_set_tunable,
.get_sset_count = bcm_phy_get_sset_count,
.get_strings = bcm_phy_get_strings,
.get_stats = bcm_omega_get_phy_stats,
.probe = bcm_omega_probe,
}
};

static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = {
{ PHY_ID_BCM_CYGNUS, 0xfffffff0, },
{ PHY_ID_BCM_OMEGA, 0xfffffff0, },
{ }
};
MODULE_DEVICE_TABLE(mdio, bcm_cygnus_phy_tbl);
Expand Down
52 changes: 52 additions & 0 deletions drivers/net/phy/bcm-phy-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,58 @@ void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
}
EXPORT_SYMBOL_GPL(bcm_phy_get_stats);

void bcm_phy_r_rc_cal_reset(struct phy_device *phydev)
{
/* Reset R_CAL/RC_CAL Engine */
bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010);

/* Disable Reset R_AL/RC_CAL Engine */
bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000);
}
EXPORT_SYMBOL_GPL(bcm_phy_r_rc_cal_reset);

int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device *phydev)
{
/* Increase VCO range to prevent unlocking problem of PLL at low
* temp
*/
bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);

/* Change Ki to 011 */
bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);

/* Disable loading of TVCO buffer to bandgap, set bandgap trim
* to 111
*/
bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);

/* Adjust bias current trim by -3 */
bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);

/* Switch to CORE_BASE1E */
phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd);

bcm_phy_r_rc_cal_reset(phydev);

/* write AFE_RXCONFIG_0 */
bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);

/* write AFE_RXCONFIG_1 */
bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);

/* write AFE_RX_LP_COUNTER */
bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);

/* write AFE_HPF_TRIM_OTHERS */
bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);

/* write AFTE_TX_CONFIG */
bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);

return 0;
}
EXPORT_SYMBOL_GPL(bcm_phy_28nm_a0b0_afe_config_init);

MODULE_DESCRIPTION("Broadcom PHY Library");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Broadcom Corporation");
20 changes: 20 additions & 0 deletions drivers/net/phy/bcm-phy-lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@
#include <linux/brcmphy.h>
#include <linux/phy.h>

/* 28nm only register definitions */
#define MISC_ADDR(base, channel) base, channel

#define DSP_TAP10 MISC_ADDR(0x0a, 0)
#define PLL_PLLCTRL_1 MISC_ADDR(0x32, 1)
#define PLL_PLLCTRL_2 MISC_ADDR(0x32, 2)
#define PLL_PLLCTRL_4 MISC_ADDR(0x33, 0)

#define AFE_RXCONFIG_0 MISC_ADDR(0x38, 0)
#define AFE_RXCONFIG_1 MISC_ADDR(0x38, 1)
#define AFE_RXCONFIG_2 MISC_ADDR(0x38, 2)
#define AFE_RX_LP_COUNTER MISC_ADDR(0x38, 3)
#define AFE_TX_CONFIG MISC_ADDR(0x39, 0)
#define AFE_VDCA_ICTRL_0 MISC_ADDR(0x39, 1)
#define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3)
#define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0)


int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);

Expand Down Expand Up @@ -45,5 +63,7 @@ int bcm_phy_get_sset_count(struct phy_device *phydev);
void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
struct ethtool_stats *stats, u64 *data);
void bcm_phy_r_rc_cal_reset(struct phy_device *phydev);
int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device *phydev);

#endif /* _LINUX_BCM_PHY_LIB_H */
Loading

0 comments on commit 83b038d

Please sign in to comment.