xref: /openbmc/linux/drivers/net/phy/broadcom.c (revision 7dd65feb)
1 /*
2  *	drivers/net/phy/broadcom.c
3  *
4  *	Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
5  *	transceivers.
6  *
7  *	Copyright (c) 2006  Maciej W. Rozycki
8  *
9  *	Inspired by code written by Amy Fong.
10  *
11  *	This program is free software; you can redistribute it and/or
12  *	modify it under the terms of the GNU General Public License
13  *	as published by the Free Software Foundation; either version
14  *	2 of the License, or (at your option) any later version.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/phy.h>
19 #include <linux/brcmphy.h>
20 
21 #define PHY_ID_BCM50610		0x0143bd60
22 #define PHY_ID_BCM50610M	0x0143bd70
23 #define PHY_ID_BCM57780		0x03625d90
24 
25 #define BRCM_PHY_MODEL(phydev) \
26 	((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
27 
28 #define BRCM_PHY_REV(phydev) \
29 	((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
30 
31 
32 #define MII_BCM54XX_ECR		0x10	/* BCM54xx extended control register */
33 #define MII_BCM54XX_ECR_IM	0x1000	/* Interrupt mask */
34 #define MII_BCM54XX_ECR_IF	0x0800	/* Interrupt force */
35 
36 #define MII_BCM54XX_ESR		0x11	/* BCM54xx extended status register */
37 #define MII_BCM54XX_ESR_IS	0x1000	/* Interrupt status */
38 
39 #define MII_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
40 #define MII_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
41 #define MII_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
42 #define MII_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
43 
44 #define MII_BCM54XX_AUX_CTL	0x18	/* Auxiliary control register */
45 #define MII_BCM54XX_ISR		0x1a	/* BCM54xx interrupt status register */
46 #define MII_BCM54XX_IMR		0x1b	/* BCM54xx interrupt mask register */
47 #define MII_BCM54XX_INT_CRCERR	0x0001	/* CRC error */
48 #define MII_BCM54XX_INT_LINK	0x0002	/* Link status changed */
49 #define MII_BCM54XX_INT_SPEED	0x0004	/* Link speed change */
50 #define MII_BCM54XX_INT_DUPLEX	0x0008	/* Duplex mode changed */
51 #define MII_BCM54XX_INT_LRS	0x0010	/* Local receiver status changed */
52 #define MII_BCM54XX_INT_RRS	0x0020	/* Remote receiver status changed */
53 #define MII_BCM54XX_INT_SSERR	0x0040	/* Scrambler synchronization error */
54 #define MII_BCM54XX_INT_UHCD	0x0080	/* Unsupported HCD negotiated */
55 #define MII_BCM54XX_INT_NHCD	0x0100	/* No HCD */
56 #define MII_BCM54XX_INT_NHCDL	0x0200	/* No HCD link */
57 #define MII_BCM54XX_INT_ANPR	0x0400	/* Auto-negotiation page received */
58 #define MII_BCM54XX_INT_LC	0x0800	/* All counters below 128 */
59 #define MII_BCM54XX_INT_HC	0x1000	/* Counter above 32768 */
60 #define MII_BCM54XX_INT_MDIX	0x2000	/* MDIX status change */
61 #define MII_BCM54XX_INT_PSERR	0x4000	/* Pair swap error */
62 
63 #define MII_BCM54XX_SHD		0x1c	/* 0x1c shadow registers */
64 #define MII_BCM54XX_SHD_WRITE	0x8000
65 #define MII_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
66 #define MII_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
67 
68 /*
69  * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
70  */
71 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
72 #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB		0x0400
73 #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA	0x0800
74 
75 #define MII_BCM54XX_AUXCTL_MISC_WREN	0x8000
76 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
77 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
78 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
79 
80 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
81 
82 
83 /*
84  * Broadcom LED source encodings.  These are used in BCM5461, BCM5481,
85  * BCM5482, and possibly some others.
86  */
87 #define BCM_LED_SRC_LINKSPD1	0x0
88 #define BCM_LED_SRC_LINKSPD2	0x1
89 #define BCM_LED_SRC_XMITLED	0x2
90 #define BCM_LED_SRC_ACTIVITYLED	0x3
91 #define BCM_LED_SRC_FDXLED	0x4
92 #define BCM_LED_SRC_SLAVE	0x5
93 #define BCM_LED_SRC_INTR	0x6
94 #define BCM_LED_SRC_QUALITY	0x7
95 #define BCM_LED_SRC_RCVLED	0x8
96 #define BCM_LED_SRC_MULTICOLOR1	0xa
97 #define BCM_LED_SRC_OPENSHORT	0xb
98 #define BCM_LED_SRC_OFF		0xe	/* Tied high */
99 #define BCM_LED_SRC_ON		0xf	/* Tied low */
100 
101 
102 /*
103  * BCM5482: Shadow registers
104  * Shadow values go into bits [14:10] of register 0x1c to select a shadow
105  * register to access.
106  */
107 /* 00101: Spare Control Register 3 */
108 #define BCM54XX_SHD_SCR3		0x05
109 #define  BCM54XX_SHD_SCR3_DEF_CLK125	0x0001
110 #define  BCM54XX_SHD_SCR3_DLLAPD_DIS	0x0002
111 #define  BCM54XX_SHD_SCR3_TRDDAPD	0x0004
112 
113 /* 01010: Auto Power-Down */
114 #define BCM54XX_SHD_APD			0x0a
115 #define  BCM54XX_SHD_APD_EN		0x0020
116 
117 #define BCM5482_SHD_LEDS1	0x0d	/* 01101: LED Selector 1 */
118 					/* LED3 / ~LINKSPD[2] selector */
119 #define BCM5482_SHD_LEDS1_LED3(src)	((src & 0xf) << 4)
120 					/* LED1 / ~LINKSPD[1] selector */
121 #define BCM5482_SHD_LEDS1_LED1(src)	((src & 0xf) << 0)
122 #define BCM54XX_SHD_RGMII_MODE	0x0b	/* 01011: RGMII Mode Selector */
123 #define BCM5482_SHD_SSD		0x14	/* 10100: Secondary SerDes control */
124 #define BCM5482_SHD_SSD_LEDM	0x0008	/* SSD LED Mode enable */
125 #define BCM5482_SHD_SSD_EN	0x0001	/* SSD enable */
126 #define BCM5482_SHD_MODE	0x1f	/* 11111: Mode Control Register */
127 #define BCM5482_SHD_MODE_1000BX	0x0001	/* Enable 1000BASE-X registers */
128 
129 
130 /*
131  * EXPANSION SHADOW ACCESS REGISTERS.  (PHY REG 0x15, 0x16, and 0x17)
132  */
133 #define MII_BCM54XX_EXP_AADJ1CH0		0x001f
134 #define  MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN	0x0200
135 #define  MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF	0x0100
136 #define MII_BCM54XX_EXP_AADJ1CH3		0x601f
137 #define  MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ	0x0002
138 #define MII_BCM54XX_EXP_EXP08			0x0F08
139 #define  MII_BCM54XX_EXP_EXP08_RJCT_2MHZ	0x0001
140 #define  MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE	0x0200
141 #define MII_BCM54XX_EXP_EXP75			0x0f75
142 #define  MII_BCM54XX_EXP_EXP75_VDACCTRL		0x003c
143 #define  MII_BCM54XX_EXP_EXP75_CM_OSC		0x0001
144 #define MII_BCM54XX_EXP_EXP96			0x0f96
145 #define  MII_BCM54XX_EXP_EXP96_MYST		0x0010
146 #define MII_BCM54XX_EXP_EXP97			0x0f97
147 #define  MII_BCM54XX_EXP_EXP97_MYST		0x0c0c
148 
149 /*
150  * BCM5482: Secondary SerDes registers
151  */
152 #define BCM5482_SSD_1000BX_CTL		0x00	/* 1000BASE-X Control */
153 #define BCM5482_SSD_1000BX_CTL_PWRDOWN	0x0800	/* Power-down SSD */
154 #define BCM5482_SSD_SGMII_SLAVE		0x15	/* SGMII Slave Register */
155 #define BCM5482_SSD_SGMII_SLAVE_EN	0x0002	/* Slave mode enable */
156 #define BCM5482_SSD_SGMII_SLAVE_AD	0x0001	/* Slave auto-detection */
157 
158 
159 /*****************************************************************************/
160 /* Fast Ethernet Transceiver definitions. */
161 /*****************************************************************************/
162 
163 #define MII_BRCM_FET_INTREG		0x1a	/* Interrupt register */
164 #define MII_BRCM_FET_IR_MASK		0x0100	/* Mask all interrupts */
165 #define MII_BRCM_FET_IR_LINK_EN		0x0200	/* Link status change enable */
166 #define MII_BRCM_FET_IR_SPEED_EN	0x0400	/* Link speed change enable */
167 #define MII_BRCM_FET_IR_DUPLEX_EN	0x0800	/* Duplex mode change enable */
168 #define MII_BRCM_FET_IR_ENABLE		0x4000	/* Interrupt enable */
169 
170 #define MII_BRCM_FET_BRCMTEST		0x1f	/* Brcm test register */
171 #define MII_BRCM_FET_BT_SRE		0x0080	/* Shadow register enable */
172 
173 
174 /*** Shadow register definitions ***/
175 
176 #define MII_BRCM_FET_SHDW_MISCCTRL	0x10	/* Shadow misc ctrl */
177 #define MII_BRCM_FET_SHDW_MC_FAME	0x4000	/* Force Auto MDIX enable */
178 
179 #define MII_BRCM_FET_SHDW_AUXMODE4	0x1a	/* Auxiliary mode 4 */
180 #define MII_BRCM_FET_SHDW_AM4_LED_MASK	0x0003
181 #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001
182 
183 #define MII_BRCM_FET_SHDW_AUXSTAT2	0x1b	/* Auxiliary status 2 */
184 #define MII_BRCM_FET_SHDW_AS2_APDE	0x0020	/* Auto power down enable */
185 
186 
187 MODULE_DESCRIPTION("Broadcom PHY driver");
188 MODULE_AUTHOR("Maciej W. Rozycki");
189 MODULE_LICENSE("GPL");
190 
191 /*
192  * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
193  * 0x1c shadow registers.
194  */
195 static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
196 {
197 	phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
198 	return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
199 }
200 
201 static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
202 {
203 	return phy_write(phydev, MII_BCM54XX_SHD,
204 			 MII_BCM54XX_SHD_WRITE |
205 			 MII_BCM54XX_SHD_VAL(shadow) |
206 			 MII_BCM54XX_SHD_DATA(val));
207 }
208 
209 /* Indirect register access functions for the Expansion Registers */
210 static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
211 {
212 	int val;
213 
214 	val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
215 	if (val < 0)
216 		return val;
217 
218 	val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
219 
220 	/* Restore default value.  It's O.K. if this write fails. */
221 	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
222 
223 	return val;
224 }
225 
226 static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
227 {
228 	int ret;
229 
230 	ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
231 	if (ret < 0)
232 		return ret;
233 
234 	ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
235 
236 	/* Restore default value.  It's O.K. if this write fails. */
237 	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
238 
239 	return ret;
240 }
241 
242 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
243 {
244 	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
245 }
246 
247 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
248 static int bcm50610_a0_workaround(struct phy_device *phydev)
249 {
250 	int err;
251 
252 	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
253 				MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
254 				MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
255 	if (err < 0)
256 		return err;
257 
258 	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
259 					MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
260 	if (err < 0)
261 		return err;
262 
263 	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
264 				MII_BCM54XX_EXP_EXP75_VDACCTRL);
265 	if (err < 0)
266 		return err;
267 
268 	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
269 				MII_BCM54XX_EXP_EXP96_MYST);
270 	if (err < 0)
271 		return err;
272 
273 	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
274 				MII_BCM54XX_EXP_EXP97_MYST);
275 
276 	return err;
277 }
278 
279 static int bcm54xx_phydsp_config(struct phy_device *phydev)
280 {
281 	int err, err2;
282 
283 	/* Enable the SMDSP clock */
284 	err = bcm54xx_auxctl_write(phydev,
285 				   MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
286 				   MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
287 				   MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
288 	if (err < 0)
289 		return err;
290 
291 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
292 	    BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
293 		/* Clear bit 9 to fix a phy interop issue. */
294 		err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
295 					MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
296 		if (err < 0)
297 			goto error;
298 
299 		if (phydev->drv->phy_id == PHY_ID_BCM50610) {
300 			err = bcm50610_a0_workaround(phydev);
301 			if (err < 0)
302 				goto error;
303 		}
304 	}
305 
306 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
307 		int val;
308 
309 		val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
310 		if (val < 0)
311 			goto error;
312 
313 		val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
314 		err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
315 	}
316 
317 error:
318 	/* Disable the SMDSP clock */
319 	err2 = bcm54xx_auxctl_write(phydev,
320 				    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
321 				    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
322 
323 	/* Return the first error reported. */
324 	return err ? err : err2;
325 }
326 
327 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
328 {
329 	u32 orig;
330 	int val;
331 	bool clk125en = true;
332 
333 	/* Abort if we are using an untested phy. */
334 	if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 ||
335 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 ||
336 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
337 		return;
338 
339 	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
340 	if (val < 0)
341 		return;
342 
343 	orig = val;
344 
345 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
346 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
347 	    BRCM_PHY_REV(phydev) >= 0x3) {
348 		/*
349 		 * Here, bit 0 _disables_ CLK125 when set.
350 		 * This bit is set by default.
351 		 */
352 		clk125en = false;
353 	} else {
354 		if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
355 			/* Here, bit 0 _enables_ CLK125 when set */
356 			val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
357 			clk125en = false;
358 		}
359 	}
360 
361 	if (clk125en == false ||
362 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
363 		val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
364 	else
365 		val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
366 
367 	if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
368 		val |= BCM54XX_SHD_SCR3_TRDDAPD;
369 
370 	if (orig != val)
371 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
372 
373 	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
374 	if (val < 0)
375 		return;
376 
377 	orig = val;
378 
379 	if (clk125en == false ||
380 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
381 		val |= BCM54XX_SHD_APD_EN;
382 	else
383 		val &= ~BCM54XX_SHD_APD_EN;
384 
385 	if (orig != val)
386 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
387 }
388 
389 static int bcm54xx_config_init(struct phy_device *phydev)
390 {
391 	int reg, err;
392 
393 	reg = phy_read(phydev, MII_BCM54XX_ECR);
394 	if (reg < 0)
395 		return reg;
396 
397 	/* Mask interrupts globally.  */
398 	reg |= MII_BCM54XX_ECR_IM;
399 	err = phy_write(phydev, MII_BCM54XX_ECR, reg);
400 	if (err < 0)
401 		return err;
402 
403 	/* Unmask events we are interested in.  */
404 	reg = ~(MII_BCM54XX_INT_DUPLEX |
405 		MII_BCM54XX_INT_SPEED |
406 		MII_BCM54XX_INT_LINK);
407 	err = phy_write(phydev, MII_BCM54XX_IMR, reg);
408 	if (err < 0)
409 		return err;
410 
411 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
412 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
413 	    (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
414 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
415 
416 	if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
417 	    (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
418 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
419 		bcm54xx_adjust_rxrefclk(phydev);
420 
421 	bcm54xx_phydsp_config(phydev);
422 
423 	return 0;
424 }
425 
426 static int bcm5482_config_init(struct phy_device *phydev)
427 {
428 	int err, reg;
429 
430 	err = bcm54xx_config_init(phydev);
431 
432 	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
433 		/*
434 		 * Enable secondary SerDes and its use as an LED source
435 		 */
436 		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
437 		bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
438 				     reg |
439 				     BCM5482_SHD_SSD_LEDM |
440 				     BCM5482_SHD_SSD_EN);
441 
442 		/*
443 		 * Enable SGMII slave mode and auto-detection
444 		 */
445 		reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
446 		err = bcm54xx_exp_read(phydev, reg);
447 		if (err < 0)
448 			return err;
449 		err = bcm54xx_exp_write(phydev, reg, err |
450 					BCM5482_SSD_SGMII_SLAVE_EN |
451 					BCM5482_SSD_SGMII_SLAVE_AD);
452 		if (err < 0)
453 			return err;
454 
455 		/*
456 		 * Disable secondary SerDes powerdown
457 		 */
458 		reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
459 		err = bcm54xx_exp_read(phydev, reg);
460 		if (err < 0)
461 			return err;
462 		err = bcm54xx_exp_write(phydev, reg,
463 					err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
464 		if (err < 0)
465 			return err;
466 
467 		/*
468 		 * Select 1000BASE-X register set (primary SerDes)
469 		 */
470 		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
471 		bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
472 				     reg | BCM5482_SHD_MODE_1000BX);
473 
474 		/*
475 		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
476 		 * (Use LED1 as secondary SerDes ACTIVITY LED)
477 		 */
478 		bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
479 			BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
480 			BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
481 
482 		/*
483 		 * Auto-negotiation doesn't seem to work quite right
484 		 * in this mode, so we disable it and force it to the
485 		 * right speed/duplex setting.  Only 'link status'
486 		 * is important.
487 		 */
488 		phydev->autoneg = AUTONEG_DISABLE;
489 		phydev->speed = SPEED_1000;
490 		phydev->duplex = DUPLEX_FULL;
491 	}
492 
493 	return err;
494 }
495 
496 static int bcm5482_read_status(struct phy_device *phydev)
497 {
498 	int err;
499 
500 	err = genphy_read_status(phydev);
501 
502 	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
503 		/*
504 		 * Only link status matters for 1000Base-X mode, so force
505 		 * 1000 Mbit/s full-duplex status
506 		 */
507 		if (phydev->link) {
508 			phydev->speed = SPEED_1000;
509 			phydev->duplex = DUPLEX_FULL;
510 		}
511 	}
512 
513 	return err;
514 }
515 
516 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
517 {
518 	int reg;
519 
520 	/* Clear pending interrupts.  */
521 	reg = phy_read(phydev, MII_BCM54XX_ISR);
522 	if (reg < 0)
523 		return reg;
524 
525 	return 0;
526 }
527 
528 static int bcm54xx_config_intr(struct phy_device *phydev)
529 {
530 	int reg, err;
531 
532 	reg = phy_read(phydev, MII_BCM54XX_ECR);
533 	if (reg < 0)
534 		return reg;
535 
536 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
537 		reg &= ~MII_BCM54XX_ECR_IM;
538 	else
539 		reg |= MII_BCM54XX_ECR_IM;
540 
541 	err = phy_write(phydev, MII_BCM54XX_ECR, reg);
542 	return err;
543 }
544 
545 static int bcm5481_config_aneg(struct phy_device *phydev)
546 {
547 	int ret;
548 
549 	/* Aneg firsly. */
550 	ret = genphy_config_aneg(phydev);
551 
552 	/* Then we can set up the delay. */
553 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
554 		u16 reg;
555 
556 		/*
557 		 * There is no BCM5481 specification available, so down
558 		 * here is everything we know about "register 0x18". This
559 		 * at least helps BCM5481 to successfuly receive packets
560 		 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
561 		 * says: "This sets delay between the RXD and RXC signals
562 		 * instead of using trace lengths to achieve timing".
563 		 */
564 
565 		/* Set RDX clk delay. */
566 		reg = 0x7 | (0x7 << 12);
567 		phy_write(phydev, 0x18, reg);
568 
569 		reg = phy_read(phydev, 0x18);
570 		/* Set RDX-RXC skew. */
571 		reg |= (1 << 8);
572 		/* Write bits 14:0. */
573 		reg |= (1 << 15);
574 		phy_write(phydev, 0x18, reg);
575 	}
576 
577 	return ret;
578 }
579 
580 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
581 {
582 	int val;
583 
584 	val = phy_read(phydev, reg);
585 	if (val < 0)
586 		return val;
587 
588 	return phy_write(phydev, reg, val | set);
589 }
590 
591 static int brcm_fet_config_init(struct phy_device *phydev)
592 {
593 	int reg, err, err2, brcmtest;
594 
595 	/* Reset the PHY to bring it to a known state. */
596 	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
597 	if (err < 0)
598 		return err;
599 
600 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
601 	if (reg < 0)
602 		return reg;
603 
604 	/* Unmask events we are interested in and mask interrupts globally. */
605 	reg = MII_BRCM_FET_IR_DUPLEX_EN |
606 	      MII_BRCM_FET_IR_SPEED_EN |
607 	      MII_BRCM_FET_IR_LINK_EN |
608 	      MII_BRCM_FET_IR_ENABLE |
609 	      MII_BRCM_FET_IR_MASK;
610 
611 	err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
612 	if (err < 0)
613 		return err;
614 
615 	/* Enable shadow register access */
616 	brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
617 	if (brcmtest < 0)
618 		return brcmtest;
619 
620 	reg = brcmtest | MII_BRCM_FET_BT_SRE;
621 
622 	err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
623 	if (err < 0)
624 		return err;
625 
626 	/* Set the LED mode */
627 	reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
628 	if (reg < 0) {
629 		err = reg;
630 		goto done;
631 	}
632 
633 	reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
634 	reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
635 
636 	err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
637 	if (err < 0)
638 		goto done;
639 
640 	/* Enable auto MDIX */
641 	err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
642 				       MII_BRCM_FET_SHDW_MC_FAME);
643 	if (err < 0)
644 		goto done;
645 
646 	if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
647 		/* Enable auto power down */
648 		err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
649 					       MII_BRCM_FET_SHDW_AS2_APDE);
650 	}
651 
652 done:
653 	/* Disable shadow register access */
654 	err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
655 	if (!err)
656 		err = err2;
657 
658 	return err;
659 }
660 
661 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
662 {
663 	int reg;
664 
665 	/* Clear pending interrupts.  */
666 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
667 	if (reg < 0)
668 		return reg;
669 
670 	return 0;
671 }
672 
673 static int brcm_fet_config_intr(struct phy_device *phydev)
674 {
675 	int reg, err;
676 
677 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
678 	if (reg < 0)
679 		return reg;
680 
681 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
682 		reg &= ~MII_BRCM_FET_IR_MASK;
683 	else
684 		reg |= MII_BRCM_FET_IR_MASK;
685 
686 	err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
687 	return err;
688 }
689 
690 static struct phy_driver bcm5411_driver = {
691 	.phy_id		= 0x00206070,
692 	.phy_id_mask	= 0xfffffff0,
693 	.name		= "Broadcom BCM5411",
694 	.features	= PHY_GBIT_FEATURES |
695 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
696 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
697 	.config_init	= bcm54xx_config_init,
698 	.config_aneg	= genphy_config_aneg,
699 	.read_status	= genphy_read_status,
700 	.ack_interrupt	= bcm54xx_ack_interrupt,
701 	.config_intr	= bcm54xx_config_intr,
702 	.driver		= { .owner = THIS_MODULE },
703 };
704 
705 static struct phy_driver bcm5421_driver = {
706 	.phy_id		= 0x002060e0,
707 	.phy_id_mask	= 0xfffffff0,
708 	.name		= "Broadcom BCM5421",
709 	.features	= PHY_GBIT_FEATURES |
710 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
711 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
712 	.config_init	= bcm54xx_config_init,
713 	.config_aneg	= genphy_config_aneg,
714 	.read_status	= genphy_read_status,
715 	.ack_interrupt	= bcm54xx_ack_interrupt,
716 	.config_intr	= bcm54xx_config_intr,
717 	.driver		= { .owner = THIS_MODULE },
718 };
719 
720 static struct phy_driver bcm5461_driver = {
721 	.phy_id		= 0x002060c0,
722 	.phy_id_mask	= 0xfffffff0,
723 	.name		= "Broadcom BCM5461",
724 	.features	= PHY_GBIT_FEATURES |
725 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
726 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
727 	.config_init	= bcm54xx_config_init,
728 	.config_aneg	= genphy_config_aneg,
729 	.read_status	= genphy_read_status,
730 	.ack_interrupt	= bcm54xx_ack_interrupt,
731 	.config_intr	= bcm54xx_config_intr,
732 	.driver		= { .owner = THIS_MODULE },
733 };
734 
735 static struct phy_driver bcm5464_driver = {
736 	.phy_id		= 0x002060b0,
737 	.phy_id_mask	= 0xfffffff0,
738 	.name		= "Broadcom BCM5464",
739 	.features	= PHY_GBIT_FEATURES |
740 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
741 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
742 	.config_init	= bcm54xx_config_init,
743 	.config_aneg	= genphy_config_aneg,
744 	.read_status	= genphy_read_status,
745 	.ack_interrupt	= bcm54xx_ack_interrupt,
746 	.config_intr	= bcm54xx_config_intr,
747 	.driver		= { .owner = THIS_MODULE },
748 };
749 
750 static struct phy_driver bcm5481_driver = {
751 	.phy_id		= 0x0143bca0,
752 	.phy_id_mask	= 0xfffffff0,
753 	.name		= "Broadcom BCM5481",
754 	.features	= PHY_GBIT_FEATURES |
755 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
756 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
757 	.config_init	= bcm54xx_config_init,
758 	.config_aneg	= bcm5481_config_aneg,
759 	.read_status	= genphy_read_status,
760 	.ack_interrupt	= bcm54xx_ack_interrupt,
761 	.config_intr	= bcm54xx_config_intr,
762 	.driver		= { .owner = THIS_MODULE },
763 };
764 
765 static struct phy_driver bcm5482_driver = {
766 	.phy_id		= 0x0143bcb0,
767 	.phy_id_mask	= 0xfffffff0,
768 	.name		= "Broadcom BCM5482",
769 	.features	= PHY_GBIT_FEATURES |
770 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
771 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
772 	.config_init	= bcm5482_config_init,
773 	.config_aneg	= genphy_config_aneg,
774 	.read_status	= bcm5482_read_status,
775 	.ack_interrupt	= bcm54xx_ack_interrupt,
776 	.config_intr	= bcm54xx_config_intr,
777 	.driver		= { .owner = THIS_MODULE },
778 };
779 
780 static struct phy_driver bcm50610_driver = {
781 	.phy_id		= PHY_ID_BCM50610,
782 	.phy_id_mask	= 0xfffffff0,
783 	.name		= "Broadcom BCM50610",
784 	.features	= PHY_GBIT_FEATURES |
785 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
786 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
787 	.config_init	= bcm54xx_config_init,
788 	.config_aneg	= genphy_config_aneg,
789 	.read_status	= genphy_read_status,
790 	.ack_interrupt	= bcm54xx_ack_interrupt,
791 	.config_intr	= bcm54xx_config_intr,
792 	.driver		= { .owner = THIS_MODULE },
793 };
794 
795 static struct phy_driver bcm50610m_driver = {
796 	.phy_id		= PHY_ID_BCM50610M,
797 	.phy_id_mask	= 0xfffffff0,
798 	.name		= "Broadcom BCM50610M",
799 	.features	= PHY_GBIT_FEATURES |
800 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
801 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
802 	.config_init	= bcm54xx_config_init,
803 	.config_aneg	= genphy_config_aneg,
804 	.read_status	= genphy_read_status,
805 	.ack_interrupt	= bcm54xx_ack_interrupt,
806 	.config_intr	= bcm54xx_config_intr,
807 	.driver		= { .owner = THIS_MODULE },
808 };
809 
810 static struct phy_driver bcm57780_driver = {
811 	.phy_id		= PHY_ID_BCM57780,
812 	.phy_id_mask	= 0xfffffff0,
813 	.name		= "Broadcom BCM57780",
814 	.features	= PHY_GBIT_FEATURES |
815 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
816 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
817 	.config_init	= bcm54xx_config_init,
818 	.config_aneg	= genphy_config_aneg,
819 	.read_status	= genphy_read_status,
820 	.ack_interrupt	= bcm54xx_ack_interrupt,
821 	.config_intr	= bcm54xx_config_intr,
822 	.driver		= { .owner = THIS_MODULE },
823 };
824 
825 static struct phy_driver bcmac131_driver = {
826 	.phy_id		= 0x0143bc70,
827 	.phy_id_mask	= 0xfffffff0,
828 	.name		= "Broadcom BCMAC131",
829 	.features	= PHY_BASIC_FEATURES |
830 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
831 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
832 	.config_init	= brcm_fet_config_init,
833 	.config_aneg	= genphy_config_aneg,
834 	.read_status	= genphy_read_status,
835 	.ack_interrupt	= brcm_fet_ack_interrupt,
836 	.config_intr	= brcm_fet_config_intr,
837 	.driver		= { .owner = THIS_MODULE },
838 };
839 
840 static int __init broadcom_init(void)
841 {
842 	int ret;
843 
844 	ret = phy_driver_register(&bcm5411_driver);
845 	if (ret)
846 		goto out_5411;
847 	ret = phy_driver_register(&bcm5421_driver);
848 	if (ret)
849 		goto out_5421;
850 	ret = phy_driver_register(&bcm5461_driver);
851 	if (ret)
852 		goto out_5461;
853 	ret = phy_driver_register(&bcm5464_driver);
854 	if (ret)
855 		goto out_5464;
856 	ret = phy_driver_register(&bcm5481_driver);
857 	if (ret)
858 		goto out_5481;
859 	ret = phy_driver_register(&bcm5482_driver);
860 	if (ret)
861 		goto out_5482;
862 	ret = phy_driver_register(&bcm50610_driver);
863 	if (ret)
864 		goto out_50610;
865 	ret = phy_driver_register(&bcm50610m_driver);
866 	if (ret)
867 		goto out_50610m;
868 	ret = phy_driver_register(&bcm57780_driver);
869 	if (ret)
870 		goto out_57780;
871 	ret = phy_driver_register(&bcmac131_driver);
872 	if (ret)
873 		goto out_ac131;
874 	return ret;
875 
876 out_ac131:
877 	phy_driver_unregister(&bcm57780_driver);
878 out_57780:
879 	phy_driver_unregister(&bcm50610m_driver);
880 out_50610m:
881 	phy_driver_unregister(&bcm50610_driver);
882 out_50610:
883 	phy_driver_unregister(&bcm5482_driver);
884 out_5482:
885 	phy_driver_unregister(&bcm5481_driver);
886 out_5481:
887 	phy_driver_unregister(&bcm5464_driver);
888 out_5464:
889 	phy_driver_unregister(&bcm5461_driver);
890 out_5461:
891 	phy_driver_unregister(&bcm5421_driver);
892 out_5421:
893 	phy_driver_unregister(&bcm5411_driver);
894 out_5411:
895 	return ret;
896 }
897 
898 static void __exit broadcom_exit(void)
899 {
900 	phy_driver_unregister(&bcmac131_driver);
901 	phy_driver_unregister(&bcm57780_driver);
902 	phy_driver_unregister(&bcm50610m_driver);
903 	phy_driver_unregister(&bcm50610_driver);
904 	phy_driver_unregister(&bcm5482_driver);
905 	phy_driver_unregister(&bcm5481_driver);
906 	phy_driver_unregister(&bcm5464_driver);
907 	phy_driver_unregister(&bcm5461_driver);
908 	phy_driver_unregister(&bcm5421_driver);
909 	phy_driver_unregister(&bcm5411_driver);
910 }
911 
912 module_init(broadcom_init);
913 module_exit(broadcom_exit);
914