xref: /linux/drivers/net/phy/broadcom.c (revision 98b8788ae91694499d1995035625bea16a4db0c4)
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 val, orig;
330 	bool clk125en = true;
331 
332 	/* Abort if we are using an untested phy. */
333 	if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 ||
334 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 ||
335 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
336 		return;
337 
338 	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
339 	if (val < 0)
340 		return;
341 
342 	orig = val;
343 
344 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
345 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
346 	    BRCM_PHY_REV(phydev) >= 0x3) {
347 		/*
348 		 * Here, bit 0 _disables_ CLK125 when set.
349 		 * This bit is set by default.
350 		 */
351 		clk125en = false;
352 	} else {
353 		if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
354 			/* Here, bit 0 _enables_ CLK125 when set */
355 			val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
356 			clk125en = false;
357 		}
358 	}
359 
360 	if (clk125en == false ||
361 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
362 		val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
363 	else
364 		val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
365 
366 	if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
367 		val |= BCM54XX_SHD_SCR3_TRDDAPD;
368 
369 	if (orig != val)
370 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
371 
372 	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
373 	if (val < 0)
374 		return;
375 
376 	orig = val;
377 
378 	if (clk125en == false ||
379 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
380 		val |= BCM54XX_SHD_APD_EN;
381 	else
382 		val &= ~BCM54XX_SHD_APD_EN;
383 
384 	if (orig != val)
385 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
386 }
387 
388 static int bcm54xx_config_init(struct phy_device *phydev)
389 {
390 	int reg, err;
391 
392 	reg = phy_read(phydev, MII_BCM54XX_ECR);
393 	if (reg < 0)
394 		return reg;
395 
396 	/* Mask interrupts globally.  */
397 	reg |= MII_BCM54XX_ECR_IM;
398 	err = phy_write(phydev, MII_BCM54XX_ECR, reg);
399 	if (err < 0)
400 		return err;
401 
402 	/* Unmask events we are interested in.  */
403 	reg = ~(MII_BCM54XX_INT_DUPLEX |
404 		MII_BCM54XX_INT_SPEED |
405 		MII_BCM54XX_INT_LINK);
406 	err = phy_write(phydev, MII_BCM54XX_IMR, reg);
407 	if (err < 0)
408 		return err;
409 
410 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
411 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
412 	    (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
413 		bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
414 
415 	if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
416 	    (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
417 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
418 		bcm54xx_adjust_rxrefclk(phydev);
419 
420 	bcm54xx_phydsp_config(phydev);
421 
422 	return 0;
423 }
424 
425 static int bcm5482_config_init(struct phy_device *phydev)
426 {
427 	int err, reg;
428 
429 	err = bcm54xx_config_init(phydev);
430 
431 	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
432 		/*
433 		 * Enable secondary SerDes and its use as an LED source
434 		 */
435 		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
436 		bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
437 				     reg |
438 				     BCM5482_SHD_SSD_LEDM |
439 				     BCM5482_SHD_SSD_EN);
440 
441 		/*
442 		 * Enable SGMII slave mode and auto-detection
443 		 */
444 		reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
445 		err = bcm54xx_exp_read(phydev, reg);
446 		if (err < 0)
447 			return err;
448 		err = bcm54xx_exp_write(phydev, reg, err |
449 					BCM5482_SSD_SGMII_SLAVE_EN |
450 					BCM5482_SSD_SGMII_SLAVE_AD);
451 		if (err < 0)
452 			return err;
453 
454 		/*
455 		 * Disable secondary SerDes powerdown
456 		 */
457 		reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
458 		err = bcm54xx_exp_read(phydev, reg);
459 		if (err < 0)
460 			return err;
461 		err = bcm54xx_exp_write(phydev, reg,
462 					err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
463 		if (err < 0)
464 			return err;
465 
466 		/*
467 		 * Select 1000BASE-X register set (primary SerDes)
468 		 */
469 		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
470 		bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
471 				     reg | BCM5482_SHD_MODE_1000BX);
472 
473 		/*
474 		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
475 		 * (Use LED1 as secondary SerDes ACTIVITY LED)
476 		 */
477 		bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
478 			BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
479 			BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
480 
481 		/*
482 		 * Auto-negotiation doesn't seem to work quite right
483 		 * in this mode, so we disable it and force it to the
484 		 * right speed/duplex setting.  Only 'link status'
485 		 * is important.
486 		 */
487 		phydev->autoneg = AUTONEG_DISABLE;
488 		phydev->speed = SPEED_1000;
489 		phydev->duplex = DUPLEX_FULL;
490 	}
491 
492 	return err;
493 }
494 
495 static int bcm5482_read_status(struct phy_device *phydev)
496 {
497 	int err;
498 
499 	err = genphy_read_status(phydev);
500 
501 	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
502 		/*
503 		 * Only link status matters for 1000Base-X mode, so force
504 		 * 1000 Mbit/s full-duplex status
505 		 */
506 		if (phydev->link) {
507 			phydev->speed = SPEED_1000;
508 			phydev->duplex = DUPLEX_FULL;
509 		}
510 	}
511 
512 	return err;
513 }
514 
515 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
516 {
517 	int reg;
518 
519 	/* Clear pending interrupts.  */
520 	reg = phy_read(phydev, MII_BCM54XX_ISR);
521 	if (reg < 0)
522 		return reg;
523 
524 	return 0;
525 }
526 
527 static int bcm54xx_config_intr(struct phy_device *phydev)
528 {
529 	int reg, err;
530 
531 	reg = phy_read(phydev, MII_BCM54XX_ECR);
532 	if (reg < 0)
533 		return reg;
534 
535 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
536 		reg &= ~MII_BCM54XX_ECR_IM;
537 	else
538 		reg |= MII_BCM54XX_ECR_IM;
539 
540 	err = phy_write(phydev, MII_BCM54XX_ECR, reg);
541 	return err;
542 }
543 
544 static int bcm5481_config_aneg(struct phy_device *phydev)
545 {
546 	int ret;
547 
548 	/* Aneg firsly. */
549 	ret = genphy_config_aneg(phydev);
550 
551 	/* Then we can set up the delay. */
552 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
553 		u16 reg;
554 
555 		/*
556 		 * There is no BCM5481 specification available, so down
557 		 * here is everything we know about "register 0x18". This
558 		 * at least helps BCM5481 to successfuly receive packets
559 		 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
560 		 * says: "This sets delay between the RXD and RXC signals
561 		 * instead of using trace lengths to achieve timing".
562 		 */
563 
564 		/* Set RDX clk delay. */
565 		reg = 0x7 | (0x7 << 12);
566 		phy_write(phydev, 0x18, reg);
567 
568 		reg = phy_read(phydev, 0x18);
569 		/* Set RDX-RXC skew. */
570 		reg |= (1 << 8);
571 		/* Write bits 14:0. */
572 		reg |= (1 << 15);
573 		phy_write(phydev, 0x18, reg);
574 	}
575 
576 	return ret;
577 }
578 
579 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
580 {
581 	int val;
582 
583 	val = phy_read(phydev, reg);
584 	if (val < 0)
585 		return val;
586 
587 	return phy_write(phydev, reg, val | set);
588 }
589 
590 static int brcm_fet_config_init(struct phy_device *phydev)
591 {
592 	int reg, err, err2, brcmtest;
593 
594 	/* Reset the PHY to bring it to a known state. */
595 	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
596 	if (err < 0)
597 		return err;
598 
599 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
600 	if (reg < 0)
601 		return reg;
602 
603 	/* Unmask events we are interested in and mask interrupts globally. */
604 	reg = MII_BRCM_FET_IR_DUPLEX_EN |
605 	      MII_BRCM_FET_IR_SPEED_EN |
606 	      MII_BRCM_FET_IR_LINK_EN |
607 	      MII_BRCM_FET_IR_ENABLE |
608 	      MII_BRCM_FET_IR_MASK;
609 
610 	err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
611 	if (err < 0)
612 		return err;
613 
614 	/* Enable shadow register access */
615 	brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
616 	if (brcmtest < 0)
617 		return brcmtest;
618 
619 	reg = brcmtest | MII_BRCM_FET_BT_SRE;
620 
621 	err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
622 	if (err < 0)
623 		return err;
624 
625 	/* Set the LED mode */
626 	reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
627 	if (reg < 0) {
628 		err = reg;
629 		goto done;
630 	}
631 
632 	reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
633 	reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
634 
635 	err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
636 	if (err < 0)
637 		goto done;
638 
639 	/* Enable auto MDIX */
640 	err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
641 				       MII_BRCM_FET_SHDW_MC_FAME);
642 	if (err < 0)
643 		goto done;
644 
645 	if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
646 		/* Enable auto power down */
647 		err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
648 					       MII_BRCM_FET_SHDW_AS2_APDE);
649 	}
650 
651 done:
652 	/* Disable shadow register access */
653 	err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
654 	if (!err)
655 		err = err2;
656 
657 	return err;
658 }
659 
660 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
661 {
662 	int reg;
663 
664 	/* Clear pending interrupts.  */
665 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
666 	if (reg < 0)
667 		return reg;
668 
669 	return 0;
670 }
671 
672 static int brcm_fet_config_intr(struct phy_device *phydev)
673 {
674 	int reg, err;
675 
676 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
677 	if (reg < 0)
678 		return reg;
679 
680 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
681 		reg &= ~MII_BRCM_FET_IR_MASK;
682 	else
683 		reg |= MII_BRCM_FET_IR_MASK;
684 
685 	err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
686 	return err;
687 }
688 
689 static struct phy_driver bcm5411_driver = {
690 	.phy_id		= 0x00206070,
691 	.phy_id_mask	= 0xfffffff0,
692 	.name		= "Broadcom BCM5411",
693 	.features	= PHY_GBIT_FEATURES |
694 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
695 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
696 	.config_init	= bcm54xx_config_init,
697 	.config_aneg	= genphy_config_aneg,
698 	.read_status	= genphy_read_status,
699 	.ack_interrupt	= bcm54xx_ack_interrupt,
700 	.config_intr	= bcm54xx_config_intr,
701 	.driver		= { .owner = THIS_MODULE },
702 };
703 
704 static struct phy_driver bcm5421_driver = {
705 	.phy_id		= 0x002060e0,
706 	.phy_id_mask	= 0xfffffff0,
707 	.name		= "Broadcom BCM5421",
708 	.features	= PHY_GBIT_FEATURES |
709 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
710 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
711 	.config_init	= bcm54xx_config_init,
712 	.config_aneg	= genphy_config_aneg,
713 	.read_status	= genphy_read_status,
714 	.ack_interrupt	= bcm54xx_ack_interrupt,
715 	.config_intr	= bcm54xx_config_intr,
716 	.driver		= { .owner = THIS_MODULE },
717 };
718 
719 static struct phy_driver bcm5461_driver = {
720 	.phy_id		= 0x002060c0,
721 	.phy_id_mask	= 0xfffffff0,
722 	.name		= "Broadcom BCM5461",
723 	.features	= PHY_GBIT_FEATURES |
724 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
725 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
726 	.config_init	= bcm54xx_config_init,
727 	.config_aneg	= genphy_config_aneg,
728 	.read_status	= genphy_read_status,
729 	.ack_interrupt	= bcm54xx_ack_interrupt,
730 	.config_intr	= bcm54xx_config_intr,
731 	.driver		= { .owner = THIS_MODULE },
732 };
733 
734 static struct phy_driver bcm5464_driver = {
735 	.phy_id		= 0x002060b0,
736 	.phy_id_mask	= 0xfffffff0,
737 	.name		= "Broadcom BCM5464",
738 	.features	= PHY_GBIT_FEATURES |
739 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
740 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
741 	.config_init	= bcm54xx_config_init,
742 	.config_aneg	= genphy_config_aneg,
743 	.read_status	= genphy_read_status,
744 	.ack_interrupt	= bcm54xx_ack_interrupt,
745 	.config_intr	= bcm54xx_config_intr,
746 	.driver		= { .owner = THIS_MODULE },
747 };
748 
749 static struct phy_driver bcm5481_driver = {
750 	.phy_id		= 0x0143bca0,
751 	.phy_id_mask	= 0xfffffff0,
752 	.name		= "Broadcom BCM5481",
753 	.features	= PHY_GBIT_FEATURES |
754 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
755 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
756 	.config_init	= bcm54xx_config_init,
757 	.config_aneg	= bcm5481_config_aneg,
758 	.read_status	= genphy_read_status,
759 	.ack_interrupt	= bcm54xx_ack_interrupt,
760 	.config_intr	= bcm54xx_config_intr,
761 	.driver		= { .owner = THIS_MODULE },
762 };
763 
764 static struct phy_driver bcm5482_driver = {
765 	.phy_id		= 0x0143bcb0,
766 	.phy_id_mask	= 0xfffffff0,
767 	.name		= "Broadcom BCM5482",
768 	.features	= PHY_GBIT_FEATURES |
769 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
770 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
771 	.config_init	= bcm5482_config_init,
772 	.config_aneg	= genphy_config_aneg,
773 	.read_status	= bcm5482_read_status,
774 	.ack_interrupt	= bcm54xx_ack_interrupt,
775 	.config_intr	= bcm54xx_config_intr,
776 	.driver		= { .owner = THIS_MODULE },
777 };
778 
779 static struct phy_driver bcm50610_driver = {
780 	.phy_id		= PHY_ID_BCM50610,
781 	.phy_id_mask	= 0xfffffff0,
782 	.name		= "Broadcom BCM50610",
783 	.features	= PHY_GBIT_FEATURES |
784 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
785 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
786 	.config_init	= bcm54xx_config_init,
787 	.config_aneg	= genphy_config_aneg,
788 	.read_status	= genphy_read_status,
789 	.ack_interrupt	= bcm54xx_ack_interrupt,
790 	.config_intr	= bcm54xx_config_intr,
791 	.driver		= { .owner = THIS_MODULE },
792 };
793 
794 static struct phy_driver bcm50610m_driver = {
795 	.phy_id		= PHY_ID_BCM50610M,
796 	.phy_id_mask	= 0xfffffff0,
797 	.name		= "Broadcom BCM50610M",
798 	.features	= PHY_GBIT_FEATURES |
799 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
800 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
801 	.config_init	= bcm54xx_config_init,
802 	.config_aneg	= genphy_config_aneg,
803 	.read_status	= genphy_read_status,
804 	.ack_interrupt	= bcm54xx_ack_interrupt,
805 	.config_intr	= bcm54xx_config_intr,
806 	.driver		= { .owner = THIS_MODULE },
807 };
808 
809 static struct phy_driver bcm57780_driver = {
810 	.phy_id		= PHY_ID_BCM57780,
811 	.phy_id_mask	= 0xfffffff0,
812 	.name		= "Broadcom BCM57780",
813 	.features	= PHY_GBIT_FEATURES |
814 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
815 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
816 	.config_init	= bcm54xx_config_init,
817 	.config_aneg	= genphy_config_aneg,
818 	.read_status	= genphy_read_status,
819 	.ack_interrupt	= bcm54xx_ack_interrupt,
820 	.config_intr	= bcm54xx_config_intr,
821 	.driver		= { .owner = THIS_MODULE },
822 };
823 
824 static struct phy_driver bcmac131_driver = {
825 	.phy_id		= 0x0143bc70,
826 	.phy_id_mask	= 0xfffffff0,
827 	.name		= "Broadcom BCMAC131",
828 	.features	= PHY_BASIC_FEATURES |
829 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
830 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
831 	.config_init	= brcm_fet_config_init,
832 	.config_aneg	= genphy_config_aneg,
833 	.read_status	= genphy_read_status,
834 	.ack_interrupt	= brcm_fet_ack_interrupt,
835 	.config_intr	= brcm_fet_config_intr,
836 	.driver		= { .owner = THIS_MODULE },
837 };
838 
839 static int __init broadcom_init(void)
840 {
841 	int ret;
842 
843 	ret = phy_driver_register(&bcm5411_driver);
844 	if (ret)
845 		goto out_5411;
846 	ret = phy_driver_register(&bcm5421_driver);
847 	if (ret)
848 		goto out_5421;
849 	ret = phy_driver_register(&bcm5461_driver);
850 	if (ret)
851 		goto out_5461;
852 	ret = phy_driver_register(&bcm5464_driver);
853 	if (ret)
854 		goto out_5464;
855 	ret = phy_driver_register(&bcm5481_driver);
856 	if (ret)
857 		goto out_5481;
858 	ret = phy_driver_register(&bcm5482_driver);
859 	if (ret)
860 		goto out_5482;
861 	ret = phy_driver_register(&bcm50610_driver);
862 	if (ret)
863 		goto out_50610;
864 	ret = phy_driver_register(&bcm50610m_driver);
865 	if (ret)
866 		goto out_50610m;
867 	ret = phy_driver_register(&bcm57780_driver);
868 	if (ret)
869 		goto out_57780;
870 	ret = phy_driver_register(&bcmac131_driver);
871 	if (ret)
872 		goto out_ac131;
873 	return ret;
874 
875 out_ac131:
876 	phy_driver_unregister(&bcm57780_driver);
877 out_57780:
878 	phy_driver_unregister(&bcm50610m_driver);
879 out_50610m:
880 	phy_driver_unregister(&bcm50610_driver);
881 out_50610:
882 	phy_driver_unregister(&bcm5482_driver);
883 out_5482:
884 	phy_driver_unregister(&bcm5481_driver);
885 out_5481:
886 	phy_driver_unregister(&bcm5464_driver);
887 out_5464:
888 	phy_driver_unregister(&bcm5461_driver);
889 out_5461:
890 	phy_driver_unregister(&bcm5421_driver);
891 out_5421:
892 	phy_driver_unregister(&bcm5411_driver);
893 out_5411:
894 	return ret;
895 }
896 
897 static void __exit broadcom_exit(void)
898 {
899 	phy_driver_unregister(&bcmac131_driver);
900 	phy_driver_unregister(&bcm57780_driver);
901 	phy_driver_unregister(&bcm50610m_driver);
902 	phy_driver_unregister(&bcm50610_driver);
903 	phy_driver_unregister(&bcm5482_driver);
904 	phy_driver_unregister(&bcm5481_driver);
905 	phy_driver_unregister(&bcm5464_driver);
906 	phy_driver_unregister(&bcm5461_driver);
907 	phy_driver_unregister(&bcm5421_driver);
908 	phy_driver_unregister(&bcm5411_driver);
909 }
910 
911 module_init(broadcom_init);
912 module_exit(broadcom_exit);
913