Skip to content

Commit a1cba56

Browse files
Arun Parameswarandavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ddc24ae commit a1cba56

File tree

8 files changed

+332
-256
lines changed

8 files changed

+332
-256
lines changed

drivers/net/phy/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,26 @@ config SMSC_PHY
6969
---help---
7070
Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
7171

72+
config BCM_NET_PHYLIB
73+
tristate
74+
7275
config BROADCOM_PHY
7376
tristate "Drivers for Broadcom PHYs"
77+
select BCM_NET_PHYLIB
7478
---help---
7579
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
7680
BCM5481 and BCM5482 PHYs.
7781

7882
config BCM63XX_PHY
7983
tristate "Drivers for Broadcom 63xx SOCs internal PHY"
8084
depends on BCM63XX
85+
select BCM_NET_PHYLIB
8186
---help---
8287
Currently supports the 6348 and 6358 PHYs.
8388

8489
config BCM7XXX_PHY
8590
tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
91+
select BCM_NET_PHYLIB
8692
---help---
8793
Currently supports the BCM7366, BCM7439, BCM7445, and
8894
40nm and 65nm generation of BCM7xxx Set Top Box SoCs.

drivers/net/phy/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
1212
obj-$(CONFIG_SMSC_PHY) += smsc.o
1313
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
1414
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
15+
obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
1516
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
1617
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
1718
obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o

drivers/net/phy/bcm-phy-lib.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright (C) 2015 Broadcom Corporation
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation version 2.
7+
*
8+
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
9+
* kind, whether express or implied; without even the implied warranty
10+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#include "bcm-phy-lib.h"
15+
#include <linux/brcmphy.h>
16+
#include <linux/export.h>
17+
#include <linux/mdio.h>
18+
#include <linux/phy.h>
19+
20+
#define MII_BCM_CHANNEL_WIDTH 0x2000
21+
#define BCM_CL45VEN_EEE_ADV 0x3c
22+
23+
int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
24+
{
25+
int rc;
26+
27+
rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
28+
if (rc < 0)
29+
return rc;
30+
31+
return phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
32+
}
33+
EXPORT_SYMBOL_GPL(bcm_phy_write_exp);
34+
35+
int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
36+
{
37+
int val;
38+
39+
val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
40+
if (val < 0)
41+
return val;
42+
43+
val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
44+
45+
/* Restore default value. It's O.K. if this write fails. */
46+
phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
47+
48+
return val;
49+
}
50+
EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
51+
52+
int bcm_phy_write_misc(struct phy_device *phydev,
53+
u16 reg, u16 chl, u16 val)
54+
{
55+
int rc;
56+
int tmp;
57+
58+
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
59+
MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
60+
if (rc < 0)
61+
return rc;
62+
63+
tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
64+
tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
65+
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
66+
if (rc < 0)
67+
return rc;
68+
69+
tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
70+
rc = bcm_phy_write_exp(phydev, tmp, val);
71+
72+
return rc;
73+
}
74+
EXPORT_SYMBOL_GPL(bcm_phy_write_misc);
75+
76+
int bcm_phy_read_misc(struct phy_device *phydev,
77+
u16 reg, u16 chl)
78+
{
79+
int rc;
80+
int tmp;
81+
82+
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
83+
MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
84+
if (rc < 0)
85+
return rc;
86+
87+
tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
88+
tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
89+
rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
90+
if (rc < 0)
91+
return rc;
92+
93+
tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
94+
rc = bcm_phy_read_exp(phydev, tmp);
95+
96+
return rc;
97+
}
98+
EXPORT_SYMBOL_GPL(bcm_phy_read_misc);
99+
100+
int bcm_phy_ack_intr(struct phy_device *phydev)
101+
{
102+
int reg;
103+
104+
/* Clear pending interrupts. */
105+
reg = phy_read(phydev, MII_BCM54XX_ISR);
106+
if (reg < 0)
107+
return reg;
108+
109+
return 0;
110+
}
111+
EXPORT_SYMBOL_GPL(bcm_phy_ack_intr);
112+
113+
int bcm_phy_config_intr(struct phy_device *phydev)
114+
{
115+
int reg;
116+
117+
reg = phy_read(phydev, MII_BCM54XX_ECR);
118+
if (reg < 0)
119+
return reg;
120+
121+
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
122+
reg &= ~MII_BCM54XX_ECR_IM;
123+
else
124+
reg |= MII_BCM54XX_ECR_IM;
125+
126+
return phy_write(phydev, MII_BCM54XX_ECR, reg);
127+
}
128+
EXPORT_SYMBOL_GPL(bcm_phy_config_intr);
129+
130+
int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow)
131+
{
132+
phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
133+
return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
134+
}
135+
EXPORT_SYMBOL_GPL(bcm_phy_read_shadow);
136+
137+
int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
138+
u16 val)
139+
{
140+
return phy_write(phydev, MII_BCM54XX_SHD,
141+
MII_BCM54XX_SHD_WRITE |
142+
MII_BCM54XX_SHD_VAL(shadow) |
143+
MII_BCM54XX_SHD_DATA(val));
144+
}
145+
EXPORT_SYMBOL_GPL(bcm_phy_write_shadow);
146+
147+
int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
148+
{
149+
int val;
150+
151+
if (dll_pwr_down) {
152+
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
153+
if (val < 0)
154+
return val;
155+
156+
val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
157+
bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
158+
}
159+
160+
val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
161+
if (val < 0)
162+
return val;
163+
164+
/* Clear APD bits */
165+
val &= BCM_APD_CLR_MASK;
166+
167+
if (phydev->autoneg == AUTONEG_ENABLE)
168+
val |= BCM54XX_SHD_APD_EN;
169+
else
170+
val |= BCM_NO_ANEG_APD_EN;
171+
172+
/* Enable energy detect single link pulse for easy wakeup */
173+
val |= BCM_APD_SINGLELP_EN;
174+
175+
/* Enable Auto Power-Down (APD) for the PHY */
176+
return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
177+
}
178+
EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
179+
180+
int bcm_phy_enable_eee(struct phy_device *phydev)
181+
{
182+
int val;
183+
184+
/* Enable EEE at PHY level */
185+
val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
186+
MDIO_MMD_AN, phydev->addr);
187+
if (val < 0)
188+
return val;
189+
190+
val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
191+
192+
phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
193+
MDIO_MMD_AN, phydev->addr, (u32)val);
194+
195+
/* Advertise EEE */
196+
val = phy_read_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
197+
MDIO_MMD_AN, phydev->addr);
198+
if (val < 0)
199+
return val;
200+
201+
val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
202+
203+
phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
204+
MDIO_MMD_AN, phydev->addr, (u32)val);
205+
206+
return 0;
207+
}
208+
EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);

drivers/net/phy/bcm-phy-lib.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (C) 2015 Broadcom Corporation
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation version 2.
7+
*
8+
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
9+
* kind, whether express or implied; without even the implied warranty
10+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef _LINUX_BCM_PHY_LIB_H
15+
#define _LINUX_BCM_PHY_LIB_H
16+
17+
#include <linux/phy.h>
18+
19+
int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
20+
int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
21+
22+
int bcm_phy_write_misc(struct phy_device *phydev,
23+
u16 reg, u16 chl, u16 value);
24+
int bcm_phy_read_misc(struct phy_device *phydev,
25+
u16 reg, u16 chl);
26+
27+
int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
28+
u16 val);
29+
int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow);
30+
31+
int bcm_phy_ack_intr(struct phy_device *phydev);
32+
int bcm_phy_config_intr(struct phy_device *phydev);
33+
34+
int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
35+
36+
int bcm_phy_enable_eee(struct phy_device *phydev);
37+
#endif /* _LINUX_BCM_PHY_LIB_H */

drivers/net/phy/bcm63xx.c

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* as published by the Free Software Foundation; either version
77
* 2 of the License, or (at your option) any later version.
88
*/
9+
#include "bcm-phy-lib.h"
910
#include <linux/module.h>
1011
#include <linux/phy.h>
1112

@@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev)
4243
return phy_write(phydev, MII_BCM63XX_IR, reg);
4344
}
4445

45-
static int bcm63xx_ack_interrupt(struct phy_device *phydev)
46-
{
47-
int reg;
48-
49-
/* Clear pending interrupts. */
50-
reg = phy_read(phydev, MII_BCM63XX_IR);
51-
if (reg < 0)
52-
return reg;
53-
54-
return 0;
55-
}
56-
57-
static int bcm63xx_config_intr(struct phy_device *phydev)
58-
{
59-
int reg, err;
60-
61-
reg = phy_read(phydev, MII_BCM63XX_IR);
62-
if (reg < 0)
63-
return reg;
64-
65-
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
66-
reg &= ~MII_BCM63XX_IR_GMASK;
67-
else
68-
reg |= MII_BCM63XX_IR_GMASK;
69-
70-
err = phy_write(phydev, MII_BCM63XX_IR, reg);
71-
return err;
72-
}
73-
7446
static struct phy_driver bcm63xx_driver[] = {
7547
{
7648
.phy_id = 0x00406000,
@@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = {
8254
.config_init = bcm63xx_config_init,
8355
.config_aneg = genphy_config_aneg,
8456
.read_status = genphy_read_status,
85-
.ack_interrupt = bcm63xx_ack_interrupt,
86-
.config_intr = bcm63xx_config_intr,
57+
.ack_interrupt = bcm_phy_ack_intr,
58+
.config_intr = bcm_phy_config_intr,
8759
.driver = { .owner = THIS_MODULE },
8860
}, {
8961
/* same phy as above, with just a different OUI */
@@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = {
9567
.config_init = bcm63xx_config_init,
9668
.config_aneg = genphy_config_aneg,
9769
.read_status = genphy_read_status,
98-
.ack_interrupt = bcm63xx_ack_interrupt,
99-
.config_intr = bcm63xx_config_intr,
70+
.ack_interrupt = bcm_phy_ack_intr,
71+
.config_intr = bcm_phy_config_intr,
10072
.driver = { .owner = THIS_MODULE },
10173
} };
10274

0 commit comments

Comments
 (0)