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: Arun Parameswaran <arunp@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ddc24ae1fd
commit
a1cba5613e
@ -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
|
|||||||
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
|
|||||||
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
|
||||||
|
208
drivers/net/phy/bcm-phy-lib.c
Normal file
208
drivers/net/phy/bcm-phy-lib.c
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
37
drivers/net/phy/bcm-phy-lib.h
Normal file
37
drivers/net/phy/bcm-phy-lib.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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 @@
|
|||||||
* 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)
|
|||||||
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[] = {
|
|||||||
.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[] = {
|
|||||||
.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 @@
|
|||||||
#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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* 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>
|
||||||
#include <linux/brcmphy.h>
|
#include <linux/brcmphy.h>
|
||||||
@ -29,39 +30,6 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
|
|||||||
MODULE_AUTHOR("Maciej W. Rozycki");
|
MODULE_AUTHOR("Maciej W. Rozycki");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
/* Indirect register access functions for the Expansion Registers */
|
|
||||||
static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
|
|
||||||
val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
|
|
||||||
|
|
||||||
/* Restore default value. It's O.K. if this write fails. */
|
|
||||||
phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
|
static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
|
||||||
{
|
{
|
||||||
return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
|
return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
|
||||||
@ -72,28 +40,28 @@ static int bcm50610_a0_workaround(struct phy_device *phydev)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
|
||||||
MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
|
MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
|
||||||
MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
|
MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
|
||||||
MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
|
MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
|
||||||
MII_BCM54XX_EXP_EXP75_VDACCTRL);
|
MII_BCM54XX_EXP_EXP75_VDACCTRL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
|
||||||
MII_BCM54XX_EXP_EXP96_MYST);
|
MII_BCM54XX_EXP_EXP96_MYST);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
|
||||||
MII_BCM54XX_EXP_EXP97_MYST);
|
MII_BCM54XX_EXP_EXP97_MYST);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -114,7 +82,7 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
|
|||||||
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
|
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
|
||||||
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
|
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
|
||||||
/* Clear bit 9 to fix a phy interop issue. */
|
/* Clear bit 9 to fix a phy interop issue. */
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
|
||||||
MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
|
MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -129,12 +97,12 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
|
|||||||
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
|
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
|
val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
|
val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
|
||||||
err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
|
err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -159,7 +127,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
|
|||||||
BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
|
BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
|
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -190,9 +158,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
|
|||||||
val |= BCM54XX_SHD_SCR3_TRDDAPD;
|
val |= BCM54XX_SHD_SCR3_TRDDAPD;
|
||||||
|
|
||||||
if (orig != val)
|
if (orig != val)
|
||||||
bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
|
bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
|
||||||
|
|
||||||
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
|
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -204,7 +172,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
|
|||||||
val &= ~BCM54XX_SHD_APD_EN;
|
val &= ~BCM54XX_SHD_APD_EN;
|
||||||
|
|
||||||
if (orig != val)
|
if (orig != val)
|
||||||
bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
|
bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcm54xx_config_init(struct phy_device *phydev)
|
static int bcm54xx_config_init(struct phy_device *phydev)
|
||||||
@ -232,7 +200,7 @@ static int bcm54xx_config_init(struct phy_device *phydev)
|
|||||||
if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
|
if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
|
||||||
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
|
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
|
||||||
(phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
|
(phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
|
||||||
bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
|
bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
|
||||||
|
|
||||||
if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
|
if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
|
||||||
(phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
|
(phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
|
||||||
@ -254,8 +222,8 @@ static int bcm5482_config_init(struct phy_device *phydev)
|
|||||||
/*
|
/*
|
||||||
* Enable secondary SerDes and its use as an LED source
|
* Enable secondary SerDes and its use as an LED source
|
||||||
*/
|
*/
|
||||||
reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
|
reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
|
||||||
bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
|
bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
|
||||||
reg |
|
reg |
|
||||||
BCM5482_SHD_SSD_LEDM |
|
BCM5482_SHD_SSD_LEDM |
|
||||||
BCM5482_SHD_SSD_EN);
|
BCM5482_SHD_SSD_EN);
|
||||||
@ -264,10 +232,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
|
|||||||
* Enable SGMII slave mode and auto-detection
|
* Enable SGMII slave mode and auto-detection
|
||||||
*/
|
*/
|
||||||
reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
|
reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
|
||||||
err = bcm54xx_exp_read(phydev, reg);
|
err = bcm_phy_read_exp(phydev, reg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = bcm54xx_exp_write(phydev, reg, err |
|
err = bcm_phy_write_exp(phydev, reg, err |
|
||||||
BCM5482_SSD_SGMII_SLAVE_EN |
|
BCM5482_SSD_SGMII_SLAVE_EN |
|
||||||
BCM5482_SSD_SGMII_SLAVE_AD);
|
BCM5482_SSD_SGMII_SLAVE_AD);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -277,10 +245,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
|
|||||||
* Disable secondary SerDes powerdown
|
* Disable secondary SerDes powerdown
|
||||||
*/
|
*/
|
||||||
reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
|
reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
|
||||||
err = bcm54xx_exp_read(phydev, reg);
|
err = bcm_phy_read_exp(phydev, reg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = bcm54xx_exp_write(phydev, reg,
|
err = bcm_phy_write_exp(phydev, reg,
|
||||||
err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
|
err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -288,15 +256,15 @@ static int bcm5482_config_init(struct phy_device *phydev)
|
|||||||
/*
|
/*
|
||||||
* Select 1000BASE-X register set (primary SerDes)
|
* Select 1000BASE-X register set (primary SerDes)
|
||||||
*/
|
*/
|
||||||
reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
|
reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
|
||||||
bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
|
bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
|
||||||
reg | BCM5482_SHD_MODE_1000BX);
|
reg | BCM5482_SHD_MODE_1000BX);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LED1=ACTIVITYLED, LED3=LINKSPD[2]
|
* LED1=ACTIVITYLED, LED3=LINKSPD[2]
|
||||||
* (Use LED1 as secondary SerDes ACTIVITY LED)
|
* (Use LED1 as secondary SerDes ACTIVITY LED)
|
||||||
*/
|
*/
|
||||||
bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
|
bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
|
||||||
BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
|
BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
|
||||||
BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
|
BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
|
||||||
|
|
||||||
@ -334,35 +302,6 @@ static int bcm5482_read_status(struct phy_device *phydev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bcm54xx_ack_interrupt(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
/* Clear pending interrupts. */
|
|
||||||
reg = phy_read(phydev, MII_BCM54XX_ISR);
|
|
||||||
if (reg < 0)
|
|
||||||
return reg;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bcm54xx_config_intr(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
int reg, err;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
err = phy_write(phydev, MII_BCM54XX_ECR, reg);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bcm5481_config_aneg(struct phy_device *phydev)
|
static int bcm5481_config_aneg(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -519,8 +458,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM5421,
|
.phy_id = PHY_ID_BCM5421,
|
||||||
@ -532,8 +471,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM5461,
|
.phy_id = PHY_ID_BCM5461,
|
||||||
@ -545,8 +484,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM54616S,
|
.phy_id = PHY_ID_BCM54616S,
|
||||||
@ -558,8 +497,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM5464,
|
.phy_id = PHY_ID_BCM5464,
|
||||||
@ -571,8 +510,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM5481,
|
.phy_id = PHY_ID_BCM5481,
|
||||||
@ -584,8 +523,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = bcm5481_config_aneg,
|
.config_aneg = bcm5481_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM5482,
|
.phy_id = PHY_ID_BCM5482,
|
||||||
@ -597,8 +536,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm5482_config_init,
|
.config_init = bcm5482_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = bcm5482_read_status,
|
.read_status = bcm5482_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM50610,
|
.phy_id = PHY_ID_BCM50610,
|
||||||
@ -610,8 +549,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM50610M,
|
.phy_id = PHY_ID_BCM50610M,
|
||||||
@ -623,8 +562,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCM57780,
|
.phy_id = PHY_ID_BCM57780,
|
||||||
@ -636,8 +575,8 @@ static struct phy_driver broadcom_drivers[] = {
|
|||||||
.config_init = bcm54xx_config_init,
|
.config_init = bcm54xx_config_init,
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = genphy_read_status,
|
||||||
.ack_interrupt = bcm54xx_ack_interrupt,
|
.ack_interrupt = bcm_phy_ack_intr,
|
||||||
.config_intr = bcm54xx_config_intr,
|
.config_intr = bcm_phy_config_intr,
|
||||||
.driver = { .owner = THIS_MODULE },
|
.driver = { .owner = THIS_MODULE },
|
||||||
}, {
|
}, {
|
||||||
.phy_id = PHY_ID_BCMAC131,
|
.phy_id = PHY_ID_BCMAC131,
|
||||||
|
@ -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 @@
|
|||||||
#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
|
||||||
|
Loading…
Reference in New Issue
Block a user