Commit a1cba561 authored by Arun Parameswaran's avatar Arun Parameswaran Committed by David S. Miller

net: phy: Add Broadcom phy library for common interfaces

This patch adds the Broadcom phy library to consolidate common
interfaces shared by Broadcom phy's.

Moved the common interfaces to the 'bcm-phy-lib.c' and updated
the Broadcom PHY drivers to use the new APIs.
Signed-off-by: default avatarArun Parameswaran <arunp@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ddc24ae1
...@@ -69,8 +69,12 @@ config SMSC_PHY ...@@ -69,8 +69,12 @@ config SMSC_PHY
---help--- ---help---
Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
config BCM_NET_PHYLIB
tristate
config BROADCOM_PHY config BROADCOM_PHY
tristate "Drivers for Broadcom PHYs" tristate "Drivers for Broadcom PHYs"
select BCM_NET_PHYLIB
---help--- ---help---
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
BCM5481 and BCM5482 PHYs. BCM5481 and BCM5482 PHYs.
...@@ -78,11 +82,13 @@ config BROADCOM_PHY ...@@ -78,11 +82,13 @@ config BROADCOM_PHY
config BCM63XX_PHY config BCM63XX_PHY
tristate "Drivers for Broadcom 63xx SOCs internal PHY" tristate "Drivers for Broadcom 63xx SOCs internal PHY"
depends on BCM63XX depends on BCM63XX
select BCM_NET_PHYLIB
---help--- ---help---
Currently supports the 6348 and 6358 PHYs. Currently supports the 6348 and 6358 PHYs.
config BCM7XXX_PHY config BCM7XXX_PHY
tristate "Drivers for Broadcom 7xxx SOCs internal PHYs" tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
select BCM_NET_PHYLIB
---help--- ---help---
Currently supports the BCM7366, BCM7439, BCM7445, and Currently supports the BCM7366, BCM7439, BCM7445, and
40nm and 65nm generation of BCM7xxx Set Top Box SoCs. 40nm and 65nm generation of BCM7xxx Set Top Box SoCs.
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o
......
/*
* Copyright (C) 2015 Broadcom Corporation
*
* 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 the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "bcm-phy-lib.h"
#include <linux/brcmphy.h>
#include <linux/export.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#define MII_BCM_CHANNEL_WIDTH 0x2000
#define BCM_CL45VEN_EEE_ADV 0x3c
int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
{
int rc;
rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
if (rc < 0)
return rc;
return phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
}
EXPORT_SYMBOL_GPL(bcm_phy_write_exp);
int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
{
int val;
val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
if (val < 0)
return val;
val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
/* Restore default value. It's O.K. if this write fails. */
phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
return val;
}
EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
int bcm_phy_write_misc(struct phy_device *phydev,
u16 reg, u16 chl, u16 val)
{
int rc;
int tmp;
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
if (rc < 0)
return rc;
tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
if (rc < 0)
return rc;
tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
rc = bcm_phy_write_exp(phydev, tmp, val);
return rc;
}
EXPORT_SYMBOL_GPL(bcm_phy_write_misc);
int bcm_phy_read_misc(struct phy_device *phydev,
u16 reg, u16 chl)
{
int rc;
int tmp;
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
if (rc < 0)
return rc;
tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
if (rc < 0)
return rc;
tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
rc = bcm_phy_read_exp(phydev, tmp);
return rc;
}
EXPORT_SYMBOL_GPL(bcm_phy_read_misc);
int bcm_phy_ack_intr(struct phy_device *phydev)
{
int reg;
/* Clear pending interrupts. */
reg = phy_read(phydev, MII_BCM54XX_ISR);
if (reg < 0)
return reg;
return 0;
}
EXPORT_SYMBOL_GPL(bcm_phy_ack_intr);
int bcm_phy_config_intr(struct phy_device *phydev)
{
int reg;
reg = phy_read(phydev, MII_BCM54XX_ECR);
if (reg < 0)
return reg;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
reg &= ~MII_BCM54XX_ECR_IM;
else
reg |= MII_BCM54XX_ECR_IM;
return phy_write(phydev, MII_BCM54XX_ECR, reg);
}
EXPORT_SYMBOL_GPL(bcm_phy_config_intr);
int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow)
{
phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
}
EXPORT_SYMBOL_GPL(bcm_phy_read_shadow);
int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
u16 val)
{
return phy_write(phydev, MII_BCM54XX_SHD,
MII_BCM54XX_SHD_WRITE |
MII_BCM54XX_SHD_VAL(shadow) |
MII_BCM54XX_SHD_DATA(val));
}
EXPORT_SYMBOL_GPL(bcm_phy_write_shadow);
int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
{
int val;
if (dll_pwr_down) {
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
if (val < 0)
return val;
val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
}
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
if (val < 0)
return val;
/* Clear APD bits */
val &= BCM_APD_CLR_MASK;
if (phydev->autoneg == AUTONEG_ENABLE)
val |= BCM54XX_SHD_APD_EN;
else
val |= BCM_NO_ANEG_APD_EN;
/* Enable energy detect single link pulse for easy wakeup */
val |= BCM_APD_SINGLELP_EN;
/* Enable Auto Power-Down (APD) for the PHY */
return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
}
EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
int bcm_phy_enable_eee(struct phy_device *phydev)
{
int val;
/* Enable EEE at PHY level */
val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
MDIO_MMD_AN, phydev->addr);
if (val < 0)
return val;
val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
MDIO_MMD_AN, phydev->addr, (u32)val);
/* Advertise EEE */
val = phy_read_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
MDIO_MMD_AN, phydev->addr);
if (val < 0)
return val;
val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
MDIO_MMD_AN, phydev->addr, (u32)val);
return 0;
}
EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);
/*
* Copyright (C) 2015 Broadcom Corporation
*
* 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 the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _LINUX_BCM_PHY_LIB_H
#define _LINUX_BCM_PHY_LIB_H
#include <linux/phy.h>
int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
int bcm_phy_write_misc(struct phy_device *phydev,
u16 reg, u16 chl, u16 value);
int bcm_phy_read_misc(struct phy_device *phydev,
u16 reg, u16 chl);
int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
u16 val);
int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow);
int bcm_phy_ack_intr(struct phy_device *phydev);
int bcm_phy_config_intr(struct phy_device *phydev);
int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
int bcm_phy_enable_eee(struct phy_device *phydev);
#endif /* _LINUX_BCM_PHY_LIB_H */
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include "bcm-phy-lib.h"
#include <linux/module.h> #include <linux/module.h>
#include <linux/phy.h> #include <linux/phy.h>
...@@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev) ...@@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev)
return phy_write(phydev, MII_BCM63XX_IR, reg); return phy_write(phydev, MII_BCM63XX_IR, reg);
} }
static int bcm63xx_ack_interrupt(struct phy_device *phydev)
{
int reg;
/* Clear pending interrupts. */
reg = phy_read(phydev, MII_BCM63XX_IR);
if (reg < 0)
return reg;
return 0;
}
static int bcm63xx_config_intr(struct phy_device *phydev)
{
int reg, err;
reg = phy_read(phydev, MII_BCM63XX_IR);
if (reg < 0)
return reg;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
reg &= ~MII_BCM63XX_IR_GMASK;
else
reg |= MII_BCM63XX_IR_GMASK;
err = phy_write(phydev, MII_BCM63XX_IR, reg);
return err;
}
static struct phy_driver bcm63xx_driver[] = { static struct phy_driver bcm63xx_driver[] = {
{ {
.phy_id = 0x00406000, .phy_id = 0x00406000,
...@@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = { ...@@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = {
.config_init = bcm63xx_config_init, .config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = bcm63xx_ack_interrupt, .ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm63xx_config_intr, .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
}, { }, {
/* same phy as above, with just a different OUI */ /* same phy as above, with just a different OUI */
...@@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = { ...@@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = {
.config_init = bcm63xx_config_init, .config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = bcm63xx_ack_interrupt, .ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm63xx_config_intr, .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
} }; } };
......
...@@ -12,12 +12,12 @@ ...@@ -12,12 +12,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "bcm-phy-lib.h"
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/brcmphy.h> #include <linux/brcmphy.h>
#include <linux/mdio.h> #include <linux/mdio.h>
/* Broadcom BCM7xxx internal PHY registers */ /* Broadcom BCM7xxx internal PHY registers */
#define MII_BCM7XXX_CHANNEL_WIDTH 0x2000
/* 40nm only register definitions */ /* 40nm only register definitions */
#define MII_BCM7XXX_100TX_AUX_CTL 0x10 #define MII_BCM7XXX_100TX_AUX_CTL 0x10
...@@ -48,37 +48,13 @@ ...@@ -48,37 +48,13 @@
#define CORE_EXPB0 0xb0 #define CORE_EXPB0 0xb0
static void phy_write_exp(struct phy_device *phydev,
u16 reg, u16 value)
{
phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg);
phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
}
static void phy_write_misc(struct phy_device *phydev,
u16 reg, u16 chl, u16 value)
{
int tmp;
phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg;
phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp);
phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
}
static void r_rc_cal_reset(struct phy_device *phydev) static void r_rc_cal_reset(struct phy_device *phydev)
{ {
/* Reset R_CAL/RC_CAL Engine */ /* Reset R_CAL/RC_CAL Engine */
phy_write_exp(phydev, 0x00b0, 0x0010); bcm_phy_write_exp(phydev, 0x00b0, 0x0010);
/* Disable Reset R_AL/RC_CAL Engine */ /* Disable Reset R_AL/RC_CAL Engine */
phy_write_exp(phydev, 0x00b0, 0x0000); bcm_phy_write_exp(phydev, 0x00b0, 0x0000);
} }
static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
...@@ -86,18 +62,18 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) ...@@ -86,18 +62,18 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
/* Increase VCO range to prevent unlocking problem of PLL at low /* Increase VCO range to prevent unlocking problem of PLL at low
* temp * temp
*/ */
phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
/* Change Ki to 011 */ /* Change Ki to 011 */
phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
/* Disable loading of TVCO buffer to bandgap, set bandgap trim /* Disable loading of TVCO buffer to bandgap, set bandgap trim
* to 111 * to 111
*/ */
phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
/* Adjust bias current trim by -3 */ /* Adjust bias current trim by -3 */
phy_write_misc(phydev, DSP_TAP10, 0x690b); bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);
/* Switch to CORE_BASE1E */ /* Switch to CORE_BASE1E */
phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd); phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd);
...@@ -105,19 +81,19 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) ...@@ -105,19 +81,19 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
r_rc_cal_reset(phydev); r_rc_cal_reset(phydev);
/* write AFE_RXCONFIG_0 */ /* write AFE_RXCONFIG_0 */
phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
/* write AFE_RXCONFIG_1 */ /* write AFE_RXCONFIG_1 */
phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
/* write AFE_RX_LP_COUNTER */ /* write AFE_RX_LP_COUNTER */
phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
/* write AFE_HPF_TRIM_OTHERS */ /* write AFE_HPF_TRIM_OTHERS */
phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
/* write AFTE_TX_CONFIG */ /* write AFTE_TX_CONFIG */
phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
return 0; return 0;
} }
...@@ -125,36 +101,36 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) ...@@ -125,36 +101,36 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
{ {
/* AFE_RXCONFIG_0 */ /* AFE_RXCONFIG_0 */
phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15); bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
/* AFE_RXCONFIG_1 */ /* AFE_RXCONFIG_1 */
phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
/* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */ /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003); bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
/* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */ /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
/* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */ /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020); bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
* offset for HT=0 code * offset for HT=0 code
*/ */
phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
phy_write_misc(phydev, DSP_TAP10, 0x011b); bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
/* Reset R_CAL/RC_CAL engine */ /* Reset R_CAL/RC_CAL engine */
r_rc_cal_reset(phydev); r_rc_cal_reset(phydev);
...@@ -165,24 +141,24 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) ...@@ -165,24 +141,24 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
{ {
/* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */ /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
* offset for HT=0 code * offset for HT=0 code
*/ */
phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
phy_write_misc(phydev, DSP_TAP10, 0x011b); bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
/* Reset R_CAL/RC_CAL engine */ /* Reset R_CAL/RC_CAL engine */
r_rc_cal_reset(phydev); r_rc_cal_reset(phydev);
...@@ -190,53 +166,6 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) ...@@ -190,53 +166,6 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
return 0; return 0;
} }
static int bcm7xxx_apd_enable(struct phy_device *phydev)
{
int val;
/* Enable powering down of the DLL during auto-power down */
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
if (val < 0)
return val;
val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
/* Enable auto-power down */
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
if (val < 0)
return val;
val |= BCM54XX_SHD_APD_EN;
return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
}
static int bcm7xxx_eee_enable(struct phy_device *phydev)
{
int val;
val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
MDIO_MMD_AN, phydev->addr);
if (val < 0)
return val;
/* Enable general EEE feature at the PHY level */
val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
MDIO_MMD_AN, phydev->addr, val);
/* Advertise supported modes */
val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN, phydev->addr);
val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN, phydev->addr, val);
return 0;
}
static int bcm7xxx_28nm_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
{ {
u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags); u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
...@@ -273,11 +202,11 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev) ...@@ -273,11 +202,11 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
if (ret) if (ret)
return ret; return ret;
ret = bcm7xxx_eee_enable(phydev); ret = bcm_phy_enable_eee(phydev);
if (ret) if (ret)
return ret; return ret;
return bcm7xxx_apd_enable(phydev); return bcm_phy_enable_apd(phydev, true);
} }
static int bcm7xxx_28nm_resume(struct phy_device *phydev) static int bcm7xxx_28nm_resume(struct phy_device *phydev)
......
This diff is collapsed.
...@@ -138,7 +138,10 @@ ...@@ -138,7 +138,10 @@
/* 01010: Auto Power-Down */ /* 01010: Auto Power-Down */
#define BCM54XX_SHD_APD 0x0a #define BCM54XX_SHD_APD 0x0a
#define BCM_APD_CLR_MASK 0xFE9F /* clear bits 5, 6 & 8 */
#define BCM54XX_SHD_APD_EN 0x0020 #define BCM54XX_SHD_APD_EN 0x0020
#define BCM_NO_ANEG_APD_EN 0x0060 /* bits 5 & 6 */
#define BCM_APD_SINGLELP_EN 0x0100 /* Bit 8 */
#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ #define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */
/* LED3 / ~LINKSPD[2] selector */ /* LED3 / ~LINKSPD[2] selector */
...@@ -209,25 +212,6 @@ ...@@ -209,25 +212,6 @@
#define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */ #define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */
#define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */ #define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */
/*
* Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
* 0x1c shadow registers.
*/
static inline int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
{
phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
}
static inline int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow,
u16 val)
{
return phy_write(phydev, MII_BCM54XX_SHD,
MII_BCM54XX_SHD_WRITE |
MII_BCM54XX_SHD_VAL(shadow) |
MII_BCM54XX_SHD_DATA(val));
}
#define BRCM_CL45VEN_EEE_CONTROL 0x803d #define BRCM_CL45VEN_EEE_CONTROL 0x803d
#define LPI_FEATURE_EN 0x8000 #define LPI_FEATURE_EN 0x8000
#define LPI_FEATURE_EN_DIG1000X 0x4000 #define LPI_FEATURE_EN_DIG1000X 0x4000
......
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