1d943d605b894926db3ed28a193f91d5ce110e29
[openwrt/staging/luka.git] /
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
2 Subject: [PATCH] net: phy: cherry-pick Broadcom drivers updates from v4.10
3 MIME-Version: 1.0
4 Content-Type: text/plain; charset=UTF-8
5 Content-Transfer-Encoding: 8bit
6
7 This includes following upstream commits:
8 5519da874ad0 net: phy: broadcom: Move bcm54xx_auxctl_{read, write} to common library
9 b14995ac2527 net: phy: broadcom: Add BCM54810 PHY entry
10 5b4e29005123 net: phy: broadcom: add bcm54xx_auxctl_read
11 d92ead16be40 net: phy: broadcom: Add support for BCM54612E
12 3cf25904fe46 net: phy: broadcom: Update Auxiliary Control Register macros
13
14 Other commits were skipped as they depend on other changes like
15 ETHTOOL_PHY_DOWNSHIFT & DOWNSHIFT_DEV_DISABLE and new APIs like
16 get_sset_count.
17
18 One exception was picking new regs from commit d06f78c4232d ("net: phy:
19 broadcom: Add support code for downshift/Wirespeed").
20
21 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
22 ---
23
24 --- a/drivers/net/phy/Kconfig
25 +++ b/drivers/net/phy/Kconfig
26 @@ -77,7 +77,7 @@ config BROADCOM_PHY
27 select BCM_NET_PHYLIB
28 ---help---
29 Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
30 - BCM5481 and BCM5482 PHYs.
31 + BCM5481, BCM54810 and BCM5482 PHYs.
32
33 config BCM_CYGNUS_PHY
34 tristate "Drivers for Broadcom Cygnus SoC internal PHY"
35 --- a/drivers/net/phy/bcm-phy-lib.c
36 +++ b/drivers/net/phy/bcm-phy-lib.c
37 @@ -50,6 +50,23 @@ int bcm_phy_read_exp(struct phy_device *
38 }
39 EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
40
41 +int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
42 +{
43 + /* The register must be written to both the Shadow Register Select and
44 + * the Shadow Read Register Selector
45 + */
46 + phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
47 + regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
48 + return phy_read(phydev, MII_BCM54XX_AUX_CTL);
49 +}
50 +EXPORT_SYMBOL_GPL(bcm54xx_auxctl_read);
51 +
52 +int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
53 +{
54 + return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
55 +}
56 +EXPORT_SYMBOL(bcm54xx_auxctl_write);
57 +
58 int bcm_phy_write_misc(struct phy_device *phydev,
59 u16 reg, u16 chl, u16 val)
60 {
61 --- a/drivers/net/phy/bcm-phy-lib.h
62 +++ b/drivers/net/phy/bcm-phy-lib.h
63 @@ -19,6 +19,9 @@
64 int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
65 int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
66
67 +int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
68 +int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
69 +
70 int bcm_phy_write_misc(struct phy_device *phydev,
71 u16 reg, u16 chl, u16 value);
72 int bcm_phy_read_misc(struct phy_device *phydev,
73 --- a/drivers/net/phy/broadcom.c
74 +++ b/drivers/net/phy/broadcom.c
75 @@ -18,7 +18,7 @@
76 #include <linux/module.h>
77 #include <linux/phy.h>
78 #include <linux/brcmphy.h>
79 -
80 +#include <linux/of.h>
81
82 #define BRCM_PHY_MODEL(phydev) \
83 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
84 @@ -30,9 +30,32 @@ MODULE_DESCRIPTION("Broadcom PHY driver"
85 MODULE_AUTHOR("Maciej W. Rozycki");
86 MODULE_LICENSE("GPL");
87
88 -static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
89 +static int bcm54810_config(struct phy_device *phydev)
90 {
91 - return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
92 + int rc, val;
93 +
94 + val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
95 + val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
96 + rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
97 + val);
98 + if (rc < 0)
99 + return rc;
100 +
101 + val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
102 + val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
103 + val |= MII_BCM54XX_AUXCTL_MISC_WREN;
104 + rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
105 + val);
106 + if (rc < 0)
107 + return rc;
108 +
109 + val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
110 + val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
111 + rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
112 + if (rc < 0)
113 + return rc;
114 +
115 + return 0;
116 }
117
118 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
119 @@ -207,6 +230,12 @@ static int bcm54xx_config_init(struct ph
120 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
121 bcm54xx_adjust_rxrefclk(phydev);
122
123 + if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
124 + err = bcm54810_config(phydev);
125 + if (err)
126 + return err;
127 + }
128 +
129 bcm54xx_phydsp_config(phydev);
130
131 return 0;
132 @@ -304,6 +333,7 @@ static int bcm5482_read_status(struct ph
133
134 static int bcm5481_config_aneg(struct phy_device *phydev)
135 {
136 + struct device_node *np = phydev->dev.of_node;
137 int ret;
138
139 /* Aneg firsly. */
140 @@ -334,6 +364,49 @@ static int bcm5481_config_aneg(struct ph
141 phy_write(phydev, 0x18, reg);
142 }
143
144 + if (of_property_read_bool(np, "enet-phy-lane-swap")) {
145 + /* Lane Swap - Undocumented register...magic! */
146 + ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
147 + 0x11B);
148 + if (ret < 0)
149 + return ret;
150 + }
151 +
152 + return ret;
153 +}
154 +
155 +static int bcm54612e_config_aneg(struct phy_device *phydev)
156 +{
157 + int ret;
158 +
159 + /* First, auto-negotiate. */
160 + ret = genphy_config_aneg(phydev);
161 +
162 + /* Clear TX internal delay unless requested. */
163 + if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
164 + (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
165 + /* Disable TXD to GTXCLK clock delay (default set) */
166 + /* Bit 9 is the only field in shadow register 00011 */
167 + bcm_phy_write_shadow(phydev, 0x03, 0);
168 + }
169 +
170 + /* Clear RX internal delay unless requested. */
171 + if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
172 + (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
173 + u16 reg;
174 +
175 + /* Errata: reads require filling in the write selector field */
176 + bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
177 + MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
178 + reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
179 + /* Disable RXD to RXC delay (default set) */
180 + reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
181 + /* Clear shadow selector field */
182 + reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
183 + bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
184 + MII_BCM54XX_AUXCTL_MISC_WREN | reg);
185 + }
186 +
187 return ret;
188 }
189
190 @@ -488,6 +561,18 @@ static struct phy_driver broadcom_driver
191 .config_intr = bcm_phy_config_intr,
192 .driver = { .owner = THIS_MODULE },
193 }, {
194 + .phy_id = PHY_ID_BCM54612E,
195 + .phy_id_mask = 0xfffffff0,
196 + .name = "Broadcom BCM54612E",
197 + .features = PHY_GBIT_FEATURES |
198 + SUPPORTED_Pause | SUPPORTED_Asym_Pause,
199 + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
200 + .config_init = bcm54xx_config_init,
201 + .config_aneg = bcm54612e_config_aneg,
202 + .read_status = genphy_read_status,
203 + .ack_interrupt = bcm_phy_ack_intr,
204 + .config_intr = bcm_phy_config_intr,
205 +}, {
206 .phy_id = PHY_ID_BCM54616S,
207 .phy_id_mask = 0xfffffff0,
208 .name = "Broadcom BCM54616S",
209 @@ -527,6 +612,18 @@ static struct phy_driver broadcom_driver
210 .config_intr = bcm_phy_config_intr,
211 .driver = { .owner = THIS_MODULE },
212 }, {
213 + .phy_id = PHY_ID_BCM54810,
214 + .phy_id_mask = 0xfffffff0,
215 + .name = "Broadcom BCM54810",
216 + .features = PHY_GBIT_FEATURES |
217 + SUPPORTED_Pause | SUPPORTED_Asym_Pause,
218 + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
219 + .config_init = bcm54xx_config_init,
220 + .config_aneg = bcm5481_config_aneg,
221 + .read_status = genphy_read_status,
222 + .ack_interrupt = bcm_phy_ack_intr,
223 + .config_intr = bcm_phy_config_intr,
224 +}, {
225 .phy_id = PHY_ID_BCM5482,
226 .phy_id_mask = 0xfffffff0,
227 .name = "Broadcom BCM5482",
228 @@ -612,9 +709,11 @@ static struct mdio_device_id __maybe_unu
229 { PHY_ID_BCM5411, 0xfffffff0 },
230 { PHY_ID_BCM5421, 0xfffffff0 },
231 { PHY_ID_BCM5461, 0xfffffff0 },
232 + { PHY_ID_BCM54612E, 0xfffffff0 },
233 { PHY_ID_BCM54616S, 0xfffffff0 },
234 { PHY_ID_BCM5464, 0xfffffff0 },
235 { PHY_ID_BCM5481, 0xfffffff0 },
236 + { PHY_ID_BCM54810, 0xfffffff0 },
237 { PHY_ID_BCM5482, 0xfffffff0 },
238 { PHY_ID_BCM50610, 0xfffffff0 },
239 { PHY_ID_BCM50610M, 0xfffffff0 },
240 --- a/include/linux/brcmphy.h
241 +++ b/include/linux/brcmphy.h
242 @@ -13,11 +13,13 @@
243 #define PHY_ID_BCM5241 0x0143bc30
244 #define PHY_ID_BCMAC131 0x0143bc70
245 #define PHY_ID_BCM5481 0x0143bca0
246 +#define PHY_ID_BCM54810 0x03625d00
247 #define PHY_ID_BCM5482 0x0143bcb0
248 #define PHY_ID_BCM5411 0x00206070
249 #define PHY_ID_BCM5421 0x002060e0
250 #define PHY_ID_BCM5464 0x002060b0
251 #define PHY_ID_BCM5461 0x002060c0
252 +#define PHY_ID_BCM54612E 0x03625e60
253 #define PHY_ID_BCM54616S 0x03625d10
254 #define PHY_ID_BCM57780 0x03625d90
255
256 @@ -55,6 +57,7 @@
257 #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
258 #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
259 #define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
260 +
261 /* Broadcom BCM7xxx specific workarounds */
262 #define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
263 #define PHY_BRCM_7XXX_PATCH(x) ((x) & 0xff)
264 @@ -105,11 +108,14 @@
265 #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800
266
267 #define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000
268 +#define MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW 0x0100
269 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
270 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
271 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
272 +#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
273 +#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN (1 << 8)
274
275 -#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
276 +#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
277
278 /*
279 * Broadcom LED source encodings. These are used in BCM5461, BCM5481,
280 @@ -124,6 +130,7 @@
281 #define BCM_LED_SRC_INTR 0x6
282 #define BCM_LED_SRC_QUALITY 0x7
283 #define BCM_LED_SRC_RCVLED 0x8
284 +#define BCM_LED_SRC_WIRESPEED 0x9
285 #define BCM_LED_SRC_MULTICOLOR1 0xa
286 #define BCM_LED_SRC_OPENSHORT 0xb
287 #define BCM_LED_SRC_OFF 0xe /* Tied high */
288 @@ -135,6 +142,14 @@
289 * Shadow values go into bits [14:10] of register 0x1c to select a shadow
290 * register to access.
291 */
292 +
293 +/* 00100: Reserved control register 2 */
294 +#define BCM54XX_SHD_SCR2 0x04
295 +#define BCM54XX_SHD_SCR2_WSPD_RTRY_DIS 0x100
296 +#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT 2
297 +#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET 2
298 +#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK 0x7
299 +
300 /* 00101: Spare Control Register 3 */
301 #define BCM54XX_SHD_SCR3 0x05
302 #define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001
303 @@ -189,6 +204,12 @@
304 #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
305 #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
306
307 +/* BCM54810 Registers */
308 +#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90)
309 +#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0)
310 +#define BCM54810_SHD_CLK_CTL 0x3
311 +#define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9)
312 +
313
314 /*****************************************************************************/
315 /* Fast Ethernet Transceiver definitions. */