Skip to content

Commit 1ad676a

Browse files
committed
Merge branch 'bcm7xxx_apd_eee'
Florian Fainelli says: ==================== net: phy: bcm7xxx: APD and EEE support This patch series enables Auto-power down and EEE for the BCM7xxx integrated Gigabit PHYs. I also put a fix for the fixed PHY that would allow clause 45 over clause 22 reads/writes but would return bogus data by using e.g: ethtool --show-eee ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5aa8dbb + b8f9a02 commit 1ad676a

File tree

6 files changed

+229
-127
lines changed

6 files changed

+229
-127
lines changed

drivers/net/phy/bcm7xxx.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/delay.h>
1515
#include <linux/bitops.h>
1616
#include <linux/brcmphy.h>
17+
#include <linux/mdio.h>
1718

1819
/* Broadcom BCM7xxx internal PHY registers */
1920
#define MII_BCM7XXX_CHANNEL_WIDTH 0x2000
@@ -146,6 +147,53 @@ static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev)
146147
return 0;
147148
}
148149

150+
static int bcm7xxx_apd_enable(struct phy_device *phydev)
151+
{
152+
int val;
153+
154+
/* Enable powering down of the DLL during auto-power down */
155+
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
156+
if (val < 0)
157+
return val;
158+
159+
val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
160+
bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
161+
162+
/* Enable auto-power down */
163+
val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
164+
if (val < 0)
165+
return val;
166+
167+
val |= BCM54XX_SHD_APD_EN;
168+
return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
169+
}
170+
171+
static int bcm7xxx_eee_enable(struct phy_device *phydev)
172+
{
173+
int val;
174+
175+
val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
176+
MDIO_MMD_AN, phydev->addr);
177+
if (val < 0)
178+
return val;
179+
180+
/* Enable general EEE feature at the PHY level */
181+
val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
182+
183+
phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
184+
MDIO_MMD_AN, phydev->addr, val);
185+
186+
/* Advertise supported modes */
187+
val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
188+
MDIO_MMD_AN, phydev->addr);
189+
190+
val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
191+
phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
192+
MDIO_MMD_AN, phydev->addr, val);
193+
194+
return 0;
195+
}
196+
149197
static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
150198
{
151199
int ret;
@@ -154,7 +202,15 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
154202
if (ret)
155203
return ret;
156204

157-
return bcm7xxx_28nm_afe_config_init(phydev);
205+
ret = bcm7xxx_28nm_afe_config_init(phydev);
206+
if (ret)
207+
return ret;
208+
209+
ret = bcm7xxx_eee_enable(phydev);
210+
if (ret)
211+
return ret;
212+
213+
return bcm7xxx_apd_enable(phydev);
158214
}
159215

160216
static int bcm7xxx_28nm_resume(struct phy_device *phydev)

drivers/net/phy/broadcom.c

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -25,132 +25,10 @@
2525
#define BRCM_PHY_REV(phydev) \
2626
((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
2727

28-
/*
29-
* Broadcom LED source encodings. These are used in BCM5461, BCM5481,
30-
* BCM5482, and possibly some others.
31-
*/
32-
#define BCM_LED_SRC_LINKSPD1 0x0
33-
#define BCM_LED_SRC_LINKSPD2 0x1
34-
#define BCM_LED_SRC_XMITLED 0x2
35-
#define BCM_LED_SRC_ACTIVITYLED 0x3
36-
#define BCM_LED_SRC_FDXLED 0x4
37-
#define BCM_LED_SRC_SLAVE 0x5
38-
#define BCM_LED_SRC_INTR 0x6
39-
#define BCM_LED_SRC_QUALITY 0x7
40-
#define BCM_LED_SRC_RCVLED 0x8
41-
#define BCM_LED_SRC_MULTICOLOR1 0xa
42-
#define BCM_LED_SRC_OPENSHORT 0xb
43-
#define BCM_LED_SRC_OFF 0xe /* Tied high */
44-
#define BCM_LED_SRC_ON 0xf /* Tied low */
45-
46-
47-
/*
48-
* BCM5482: Shadow registers
49-
* Shadow values go into bits [14:10] of register 0x1c to select a shadow
50-
* register to access.
51-
*/
52-
/* 00101: Spare Control Register 3 */
53-
#define BCM54XX_SHD_SCR3 0x05
54-
#define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001
55-
#define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002
56-
#define BCM54XX_SHD_SCR3_TRDDAPD 0x0004
57-
58-
/* 01010: Auto Power-Down */
59-
#define BCM54XX_SHD_APD 0x0a
60-
#define BCM54XX_SHD_APD_EN 0x0020
61-
62-
#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */
63-
/* LED3 / ~LINKSPD[2] selector */
64-
#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4)
65-
/* LED1 / ~LINKSPD[1] selector */
66-
#define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0)
67-
#define BCM54XX_SHD_RGMII_MODE 0x0b /* 01011: RGMII Mode Selector */
68-
#define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */
69-
#define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */
70-
#define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */
71-
#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */
72-
#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
73-
74-
75-
/*
76-
* EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17)
77-
*/
78-
#define MII_BCM54XX_EXP_AADJ1CH0 0x001f
79-
#define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200
80-
#define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100
81-
#define MII_BCM54XX_EXP_AADJ1CH3 0x601f
82-
#define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002
83-
#define MII_BCM54XX_EXP_EXP08 0x0F08
84-
#define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001
85-
#define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200
86-
#define MII_BCM54XX_EXP_EXP75 0x0f75
87-
#define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c
88-
#define MII_BCM54XX_EXP_EXP75_CM_OSC 0x0001
89-
#define MII_BCM54XX_EXP_EXP96 0x0f96
90-
#define MII_BCM54XX_EXP_EXP96_MYST 0x0010
91-
#define MII_BCM54XX_EXP_EXP97 0x0f97
92-
#define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c
93-
94-
/*
95-
* BCM5482: Secondary SerDes registers
96-
*/
97-
#define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */
98-
#define BCM5482_SSD_1000BX_CTL_PWRDOWN 0x0800 /* Power-down SSD */
99-
#define BCM5482_SSD_SGMII_SLAVE 0x15 /* SGMII Slave Register */
100-
#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
101-
#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
102-
103-
104-
/*****************************************************************************/
105-
/* Fast Ethernet Transceiver definitions. */
106-
/*****************************************************************************/
107-
108-
#define MII_BRCM_FET_INTREG 0x1a /* Interrupt register */
109-
#define MII_BRCM_FET_IR_MASK 0x0100 /* Mask all interrupts */
110-
#define MII_BRCM_FET_IR_LINK_EN 0x0200 /* Link status change enable */
111-
#define MII_BRCM_FET_IR_SPEED_EN 0x0400 /* Link speed change enable */
112-
#define MII_BRCM_FET_IR_DUPLEX_EN 0x0800 /* Duplex mode change enable */
113-
#define MII_BRCM_FET_IR_ENABLE 0x4000 /* Interrupt enable */
114-
115-
#define MII_BRCM_FET_BRCMTEST 0x1f /* Brcm test register */
116-
#define MII_BRCM_FET_BT_SRE 0x0080 /* Shadow register enable */
117-
118-
119-
/*** Shadow register definitions ***/
120-
121-
#define MII_BRCM_FET_SHDW_MISCCTRL 0x10 /* Shadow misc ctrl */
122-
#define MII_BRCM_FET_SHDW_MC_FAME 0x4000 /* Force Auto MDIX enable */
123-
124-
#define MII_BRCM_FET_SHDW_AUXMODE4 0x1a /* Auxiliary mode 4 */
125-
#define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003
126-
#define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001
127-
128-
#define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */
129-
#define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */
130-
131-
13228
MODULE_DESCRIPTION("Broadcom PHY driver");
13329
MODULE_AUTHOR("Maciej W. Rozycki");
13430
MODULE_LICENSE("GPL");
13531

136-
/*
137-
* Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
138-
* 0x1c shadow registers.
139-
*/
140-
static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
141-
{
142-
phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
143-
return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
144-
}
145-
146-
static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
147-
{
148-
return phy_write(phydev, MII_BCM54XX_SHD,
149-
MII_BCM54XX_SHD_WRITE |
150-
MII_BCM54XX_SHD_VAL(shadow) |
151-
MII_BCM54XX_SHD_DATA(val));
152-
}
153-
15432
/* Indirect register access functions for the Expansion Registers */
15533
static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
15634
{

drivers/net/phy/fixed.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
124124
if (reg_num >= MII_REGS_NUM)
125125
return -1;
126126

127+
/* We do not support emulating Clause 45 over Clause 22 register reads
128+
* return an error instead of bogus data.
129+
*/
130+
switch (reg_num) {
131+
case MII_MMD_CTRL:
132+
case MII_MMD_DATA:
133+
return -1;
134+
default:
135+
break;
136+
}
137+
127138
list_for_each_entry(fp, &fmb->phys, node) {
128139
if (fp->addr == phy_addr) {
129140
/* Issue callback if user registered it. */

drivers/net/phy/phy.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
955955
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
956956
* 3) Read reg 14 // Read MMD data
957957
*/
958-
static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
958+
int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
959959
int devad, int addr)
960960
{
961961
struct phy_driver *phydrv = phydev->drv;
@@ -971,6 +971,7 @@ static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
971971
}
972972
return value;
973973
}
974+
EXPORT_SYMBOL(phy_read_mmd_indirect);
974975

975976
/**
976977
* phy_write_mmd_indirect - writes data to the MMD registers
@@ -988,7 +989,7 @@ static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
988989
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
989990
* 3) Write reg 14 // Write MMD data
990991
*/
991-
static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
992+
void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
992993
int devad, int addr, u32 data)
993994
{
994995
struct phy_driver *phydrv = phydev->drv;
@@ -1002,6 +1003,7 @@ static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
10021003
phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
10031004
}
10041005
}
1006+
EXPORT_SYMBOL(phy_write_mmd_indirect);
10051007

10061008
/**
10071009
* phy_init_eee - init and check the EEE feature
@@ -1017,12 +1019,14 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
10171019
{
10181020
/* According to 802.3az,the EEE is supported only in full duplex-mode.
10191021
* Also EEE feature is active when core is operating with MII, GMII
1020-
* or RGMII.
1022+
* or RGMII. Internal PHYs are also allowed to proceed and should
1023+
* return an error if they do not support EEE.
10211024
*/
10221025
if ((phydev->duplex == DUPLEX_FULL) &&
10231026
((phydev->interface == PHY_INTERFACE_MODE_MII) ||
10241027
(phydev->interface == PHY_INTERFACE_MODE_GMII) ||
1025-
(phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
1028+
(phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
1029+
phy_is_internal(phydev))) {
10261030
int eee_lp, eee_cap, eee_adv;
10271031
u32 lp, cap, adv;
10281032
int status;

0 commit comments

Comments
 (0)